package com.xjrsoft.core.tool.utils;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Entity;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.xjrsoft.common.Enum.DeleteMarkEnum;
import com.xjrsoft.common.Enum.EnabledMarkEnum;
import com.xjrsoft.common.config.ServerConfig;
import com.xjrsoft.common.dbmodel.DbExecutor;
import com.xjrsoft.common.flowableUtils.MyProcessDiagramGenerator;
import com.xjrsoft.common.page.ConventPage;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.common.utils.RedisUtil;
import com.xjrsoft.core.constant.FlowEngineConstant;
import com.xjrsoft.core.secure.XjrUser;
import com.xjrsoft.core.secure.utils.SecureUtil;
import com.xjrsoft.module.base.dto.GetPageListDto;
import com.xjrsoft.module.base.entity.*;
import com.xjrsoft.module.base.service.*;
import com.xjrsoft.module.base.utils.OrganizationCacheUtil;
import com.xjrsoft.module.base.vo.SpecialPostUserVo;
import com.xjrsoft.module.form.constant.FormConstants;
import com.xjrsoft.module.form.entity.XjrFormScheme;
import com.xjrsoft.module.form.entity.XjrFormSchemeInfo;
import com.xjrsoft.module.form.service.IXjrFormRelationService;
import com.xjrsoft.module.form.service.IXjrFormSchemeInfoService;
import com.xjrsoft.module.form.service.IXjrFormSchemeService;
import com.xjrsoft.module.form.util.FormDataUtil;
import com.xjrsoft.module.interfaceManager.service.IXjrInterfaceInfoService;
import com.xjrsoft.module.language.entity.XjrLgMark;
import com.xjrsoft.module.language.service.IXjrLgMarkService;
import com.xjrsoft.module.oa.utils.SendMessageUtil;
import com.xjrsoft.module.workflow.dto.GetPageHistoryDto;
import com.xjrsoft.module.workflow.dto.GetPageListNwfTaskDto;
import com.xjrsoft.module.workflow.entity.XjrNwfDelegateRule;
import com.xjrsoft.module.workflow.entity.XjrNwfDelegaterelation;
import com.xjrsoft.module.workflow.entity.XjrNwfScheme;
import com.xjrsoft.module.workflow.entity.XjrNwfSchemeinfo;
import com.xjrsoft.module.workflow.mapper.NwfTaskMapper;
import com.xjrsoft.module.workflow.service.*;
import io.jsonwebtoken.lang.Collections;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import oracle.sql.CLOB;
import oracle.sql.NCLOB;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.collections.CaseInsensitiveKeyMap;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.editor.constants.ModelDataJsonConstants;
import org.flowable.editor.language.json.converter.BpmnJsonConverter;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.RepositoryServiceImpl;
import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.flowable.engine.impl.dynamic.DynamicUserTaskBuilder;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.DeploymentBuilder;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static org.flowable.editor.constants.ModelDataJsonConstants.*;

/**
 * @Author:湘北智造-框架开发组
 * @Date:2020/10/19
 * @Description:工作流工具类
 */
@Slf4j
public class FlowableUtil {

    private final static RepositoryService repositoryService;

    private final static RuntimeService runtimeService;

    private final static TaskService taskService;

    private final static HistoryService historyService;

    private final static FormService formService;

    private final static IdentityService identityService;

    private final static ProcessEngineConfiguration processEngineConfiguration;

    private final static IXjrBaseTempfieldService xjrBaseTempfieldService;

    private final static IXjrNwfSchemeService nwfSchemeService;

    private final static IXjrNwfSchemeInfoService nwfSchemeInfoService;

    private final static IXjrNwfRelationService nwfRelationService;

    private final static IXjrBaseUserService userService;

    private final static IXjrBaseStampService bseStampService;

    private final static IXjrNwfDelegateRuleService delegateruleService;

    private final static RedisUtil redisUtil;

    private final static IXjrNwfDelegateRelationService nwfDelegateRelationService;

    private final static IXjrBaseUserRelationService userRelationService;

    private final static IXjrFormSchemeInfoService formSchemeInfoService;

    private final static IXjrFormSchemeService formSchemeService;

    private final static IXjrBaseCompanyService companyService;

    private final static IXjrBaseDepartmentService departmentService;

    private final static IXjrBasePostService postService;

    private final static IXjrNwfTaskService nwfTaskService;

    private final static DbExecutor dbExecutor;

    private final static DynamicBpmnService bpmnService;

    private final static IXjrBaseRoleService roleService;

    private final static RestTemplate restTemplate;

    private final static ServerConfig serverConfig;

    private final static NwfTaskMapper nwfTaskMapper;

    private final static IXjrBaseAnnexesFileService annexesFileService;


    private final static IXjrBaseDataItemDetailService dataItemDetailService;

    private final static IXjrFormRelationService formRelationService;

    private final static IXjrInterfaceInfoService infoService;

    private final static IXjrLgMarkService lgMarkService;

    private final static IXjrBaseDatabaseLinkService databaselinkService;

    static {
        infoService = SpringUtil.getBean(IXjrInterfaceInfoService.class);
        formRelationService = SpringUtil.getBean(IXjrFormRelationService.class);
        dataItemDetailService = SpringUtil.getBean(IXjrBaseDataItemDetailService.class);
        annexesFileService = SpringUtil.getBean(IXjrBaseAnnexesFileService.class);
        repositoryService = SpringUtil.getBean(RepositoryService.class);
        runtimeService = SpringUtil.getBean(RuntimeService.class);
        taskService = SpringUtil.getBean(TaskService.class);
        historyService = SpringUtil.getBean(HistoryService.class);
        formService = SpringUtil.getBean(FormService.class);
        identityService = SpringUtil.getBean(IdentityService.class);
        processEngineConfiguration = SpringUtil.getBean(ProcessEngineConfiguration.class);
        xjrBaseTempfieldService = SpringUtil.getBean(IXjrBaseTempfieldService.class);
        nwfSchemeInfoService = SpringUtil.getBean(IXjrNwfSchemeInfoService.class);
        bseStampService = SpringUtil.getBean(IXjrBaseStampService.class);
        nwfRelationService = SpringUtil.getBean(IXjrNwfRelationService.class);
        userService = SpringUtil.getBean(IXjrBaseUserService.class);
        delegateruleService = SpringUtil.getBean(IXjrNwfDelegateRuleService.class);
        redisUtil = SpringUtil.getBean(RedisUtil.class);
        nwfDelegateRelationService = SpringUtil.getBean(IXjrNwfDelegateRelationService.class);
        userRelationService = SpringUtil.getBean(IXjrBaseUserRelationService.class);
        formSchemeInfoService = SpringUtil.getBean(IXjrFormSchemeInfoService.class);
        formSchemeService = SpringUtil.getBean(IXjrFormSchemeService.class);
        companyService = SpringUtil.getBean(IXjrBaseCompanyService.class);
        departmentService = SpringUtil.getBean(IXjrBaseDepartmentService.class);
        postService = SpringUtil.getBean(IXjrBasePostService.class);
        nwfTaskService = SpringUtil.getBean(IXjrNwfTaskService.class);
        nwfSchemeService = SpringUtil.getBean(IXjrNwfSchemeService.class);
        dbExecutor = SpringUtil.getBean(DbExecutor.class);
        bpmnService = SpringUtil.getBean(DynamicBpmnService.class);
        roleService = SpringUtil.getBean(IXjrBaseRoleService.class);
        restTemplate = SpringUtil.getBean(RestTemplate.class);
        serverConfig = SpringUtil.getBean(ServerConfig.class);
        nwfTaskMapper = SpringUtil.getBean(NwfTaskMapper.class);
        lgMarkService = SpringUtil.getBean(IXjrLgMarkService.class);
        databaselinkService = SpringUtil.getBean(IXjrBaseDatabaseLinkService.class);
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/19
     * @Param:[]
     * @return:java.lang.String:返回modelId
     * @Description:新建模型
     */
    @SneakyThrows
    public static String newModel() {
        // 初始化一个空模型
        Model model = repositoryService.newModel();
        // 设置一些默认信息
        String name = "new-process" + IdWorker.get32UUID();
        String description = "description" + IdWorker.get32UUID();
        int revision = 1;
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode modelNode = objectMapper.createObjectNode();
        modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
        modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
        modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);

        model.setName(name);
        model.setMetaInfo(modelNode.toString());
        repositoryService.saveModel(model);
        String id = model.getId();
        // 完善ModelEditorSource
//        ObjectNode editorNode = objectMapper.createObjectNode();
//        editorNode.put("id", "canvas");
//        editorNode.put("resourceId", "canvas");
//        ObjectNode stencilSetNode = objectMapper.createObjectNode();
//        stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
//        editorNode.put("stencilset", stencilSetNode);
//        repositoryService.addModelEditorSource(id, editorNode.toString().getBytes("utf-8"));
        return id;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/19
     * @Param:[modelId]
     * @return:com.fasterxml.jackson.databind.node.ObjectNode
     * @Description:编辑模板
     */
    public static ObjectNode getEditorJson(String modelId) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode modelNode = null;
        Model model = repositoryService.getModel(modelId);
        if (model != null) {
            if (StringUtils.isNotEmpty(model.getMetaInfo())) {
                modelNode = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
            } else {
                modelNode = objectMapper.createObjectNode();
                modelNode.put(MODEL_NAME, model.getName());
            }
            modelNode.put(MODEL_ID, model.getId());
            ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(new String(repositoryService.getModelEditorSource(model.getId()), "utf-8"));
            modelNode.put("model", editorJsonNode);
        }
        return modelNode;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/19
     * @Param:[modelId, jsonStr, schemeName, userId]
     * @return:java.lang.Object
     * @Description:根据json部署流程
     */
    public static String deployByJson(String modelId, String json, String schemeName, String userId) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        Model model = repositoryService.getModel(modelId);
        ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
        modelJson.put(MODEL_NAME, schemeName);
        modelJson.put(MODEL_DESCRIPTION, "description");
        model.setMetaInfo(modelJson.toString());
        model.setName(schemeName);
//        repositoryService.saveModel(model);
//        repositoryService.addModelEditorSource(model.getId(), json.getBytes("utf-8"));
        byte[] bytes = json.getBytes("UTF-8");
        if (bytes == null) {
            return "模型数据为空，请先设计流程并成功保存，再进行发布。";
        }
        log.info("【bytes-------->】" + new String(bytes));
        JsonNode modelNode = new ObjectMapper().readTree(bytes);
        BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(modelNode);
        Map<String, GraphicInfo> locationMap = bpmnModel.getLocationMap();
        Set<Map.Entry<String, GraphicInfo>> entries = locationMap.entrySet();
        double differenceValueX = 0;
        double differenceValueY = 0;
        int index = 1;
        for (Map.Entry<String, GraphicInfo> entry : entries) {
            GraphicInfo graphicInfo = entry.getValue();
            double x = graphicInfo.getX();
            double y = graphicInfo.getY();
            if (index == 1) {
                if (x <= 100 && y <= 50) {
                    break;
                }
                if (x > 100) {
                    differenceValueX = x - 100;
                    graphicInfo.setX(100);
                }
                if (y > 50) {
                    differenceValueY = y - 50;
                    graphicInfo.setY(50);
                }
            } else {
                graphicInfo.setX(x - differenceValueX);
                graphicInfo.setY(y - differenceValueY);
            }
            index = index + 1;
        }
        BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
        byte[] convertToXML = bpmnXMLConverter.convertToXML(bpmnModel);
        String xml = new String(convertToXML);
        if (bpmnModel.getProcesses().size() == 0) {
            return "数据模型不符要求，请至少设计一条主线流程。";
        }
        String processName = model.getName() + ".bpmn20.xml";
        // 部署流程
        DeploymentBuilder builder = repositoryService.createDeployment();
        // 添加流程模板名称
        builder.name(schemeName);
        builder.key(model.getKey());
        // 用来保存创建用户的id
        builder.category(userId);
        builder.addBpmnModel(processName, bpmnModel);
        Deployment deployment = builder.deploy();
        model.setDeploymentId(deployment.getId());
        repositoryService.saveModel(model);
//        repositoryService.addModelEditorSource(model.getId(), json.getBytes("utf-8"));
        return deployment.getId();
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/19
     * @Param:[modelId, name, description, jsonXml, svgXml]
     * @return:boolean
     * @Description:保存模板
     */
//    public static boolean saveModel(String modelId, String name, String description, String json) throws Exception {
//        ObjectMapper objectMapper = new ObjectMapper();
//        Model model = repositoryService.getModel(modelId);
//        ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
//        modelJson.put(MODEL_NAME, name);
//        modelJson.put(MODEL_DESCRIPTION, description);
//        model.setMetaInfo(modelJson.toString());
//        model.setName(name);
//        repositoryService.saveModel(model);
//        repositoryService.addModelEditorSource(model.getId(), json.getBytes("utf-8"));
//        return true;
//    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/19
     * @Param:[modelId]
     * @return:java.lang.String
     * @Description:json转xml
     */
    public static String json2Xml(String deploymentId) {
        String xml = null;
        // 根据modelId使json转Xml
        if (StringUtils.isNotBlank(deploymentId)) {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
            if (processDefinition != null) {
                String schemeInfoId = processDefinition.getDescription();
                XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(schemeInfoId + StringPool.UNDERSCORE + deploymentId, "31");
                if (xjrBaseTempfield != null) {
                    xml = xjrBaseTempfield.getFvalue();
                }
            }
        }
        return xml;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/19
     * @Param:[deploymentId]
     * @return:void
     * @Description:删除流程定义
     */
    public static void deleteProcessDefi(String deploymentId) {
        repositoryService.deleteDeployment(deploymentId, true);
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/12/9
     * @Param:[modelId]
     * @return:void
     * @Description:删除流程模板
     */
    public static void deleteModel(String modelId) {
        repositoryService.deleteModel(modelId);
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/19
     * @Param:[deploymentId部署ID]
     * @return:java.lang.Boolean
     * @Description:已经停止,false:没有停止
     */
    public static Boolean validateProBydepId(String deploymentId) {
        return runtimeService.createProcessInstanceQuery().deploymentId("deploymentId").list().size() > 0;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/21
     * @Param:[deployId, currentUser, keyValue, paramMap, nwfSchemeInfoId, userJson]
     * @return:java.util.Map<java.lang.String,java.lang.Object>
     * @Description:提交表单,启动流程
     */
    public static JSONObject startProcessInstance(String deployId, String currentUserId, String keyValue, XjrNwfScheme xjrNwfScheme) throws Exception {
        // 根据部署id查询流程定义，
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
        // 获取表单数据
        Map<String, Object> formValues = getFormData(keyValue, null, xjrNwfScheme.getSchemeInfoId(), deployId);
        formValues.putAll(setParamVariable(null, processDefinition.getId(), xjrNwfScheme, formValues, null));
        // 获取会签节点的获选人
        //获取下一个会签节点
        String fjson = xjrNwfScheme.getFjson();
        JSONArray childShapes = (JSONObject.parseObject(fjson)).getJSONArray("childShapes");
        Optional<Object> startNode = childShapes.stream().filter(s -> "StartNoneEvent".equals(((JSONObject) s).getJSONObject("stencil").getString("id"))).findFirst();
        if (startNode.isPresent()) {
            Object node = startNode.get();
            String currentResourceId = ((JSONObject) node).getString("resourceId");
            JSONArray nextMultiinstanceResourceId = JsonUtil.getNextMultiinstanceResourceId(childShapes, currentResourceId);

//            for (int i = 0; i < nextMultiinstanceResourceId.size(); i++) {
//                String resourceId = nextMultiinstanceResourceId.getString(i);
//                XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(xjrNwfScheme.getSchemeInfoId() + StringPool.UNDERSCORE + nextMultiinstanceResourceId.getString(i) + StringPool.UNDERSCORE + String.valueOf(processDefinition.getVersion()), "1");
//                if (xjrBaseTempfield != null) {
//                    //为会签
//                    JSONArray userArray = new JSONArray();
//                    userArray.add("xxx");
//                    formValues.put(resourceId + StringPool.UNDERSCORE + "usernamelist", userArray);
//                }
//            }
            List<FlowElement> nodes = getCallActivityNode(currentResourceId, processDefinition.getId(), 1, new ArrayList<String>());
            if (CollectionUtil.isNotEmpty(nodes)) {
                for (FlowElement flowElement : nodes) {
                    if (flowElement instanceof Activity) {
                        String activityId = flowElement.getId();
                        XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(processDefinition.getDescription() + StringPool.UNDERSCORE + activityId + StringPool.UNDERSCORE + String.valueOf(processDefinition.getVersion()), "39");
                        if (xjrBaseTempfield != null) {
                            String properties = xjrBaseTempfield.getFvalue();
                            JSONObject propertiesObj = JSONObject.parseObject(properties);
                            Boolean callType = propertiesObj.getBoolean("callType");
                            if (!callType) {
                                //多实例
                                JSONArray callStartUser = getCallStartUser(propertiesObj, null, processDefinition.getDescription(), formValues);
                                if (CollectionUtil.isEmpty(callStartUser)) {
                                    throw new Exception(flowElement.getName() + "节点发起人集合为空!");
                                }
                                formValues.put(activityId + StringPool.UNDERSCORE + "usernamelist", callStartUser);
                                formValues.put(activityId + StringPool.UNDERSCORE + "count", callStartUser.size());
                            }
                        }
                    }
                }
            }
        }
        //表单绑定流程key
        JSONArray keyValueArray = JSONArray.parseArray(keyValue);
        for (
                int i = 0; i < keyValueArray.size(); i++) {
            JSONObject jsonObject = keyValueArray.getJSONObject(i);
            String key = jsonObject.getString("F_FormId") + StringPool.UNDERSCORE + jsonObject.getString("F_Id");
            formValues.put(key, key);
        }
        identityService.setAuthenticatedUserId(currentUserId);
        ProcessInstance processInstance = null;
        try {
            processInstance = runtimeService.startProcessInstanceById(processDefinition.getId(), keyValue, formValues);
        } catch (Exception e) {
            if (StringUtil.startsWithIgnoreCase(e.getMessage(), "No outgoing sequence flow")) {
                throw new Exception("当前审批不满足任一流转条件，请修改数据或联系管理员");
            } else {
                log.error("流程流转发生错误，错误原因:" + e.getMessage());
                throw new Exception("流程流转发生错误，具体错误请在控制台或日志中查看");
            }
        }
        // 2.自定义任务命名
        JSONObject result = new JSONObject();
        if (processInstance != null) {
            taskNameRule(processDefinition.getId(), processInstance.getProcessInstanceId());
            //        //保存开始节点绑定的表单信息
            XjrBaseTempfield startFormInfo = new XjrBaseTempfield();
            startFormInfo.setType("25");
            startFormInfo.setFvalue(keyValue);
            startFormInfo.setFkey(processInstance.getId() + StringPool.UNDERSCORE + ((ExecutionEntity) processInstance).getStartActivityId());
            xjrBaseTempfieldService.save(startFormInfo);
            // 任务预处理
            result = pretreatmentTask(processInstance.getId(), deployId, null);
            result.put("processInstanceId", processInstance.getId());
        }
        return result;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/19
     * @Param:[deployId]
     * @return:java.lang.String[]
     * @Description:读取启动节点的表单key
     */
    public static String[] readStartForm(String deployId) {
        String[] ids = null;
        // 根据部署id查询
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
        if (processDefinition != null) {
            String processDefinitionId = processDefinition.getId();
            String startFormKey = formService.getStartFormKey(processDefinitionId);
            if (StringUtils.isNotEmpty(startFormKey)) {
                ids = startFormKey.split(",");
            }
        }
        return ids;
    }


    //设置或更新流程参数到流程变量
    public static Map<String, Object> setParamVariable(String taskId, String ProcessDefinitionId, XjrNwfScheme xjrNwfScheme, Map<String, Object> formValues, String processInstanceId) throws Exception {
        String currentResourceId = "";
        Map<String, Object> paramMap = new HashMap<>();
        XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(xjrNwfScheme.getSchemeInfoId());
        if (StringUtil.isBlank(taskId)) {
            //获取开始节点的流程参数信息
            JSONObject jsonObject = JSON.parseObject(xjrNwfScheme.getFjson());
            JSONArray childShapes = jsonObject.getJSONArray("childShapes");
            Optional<Object> startNode = childShapes.stream().filter(s -> "StartNoneEvent".equals(((JSONObject) s).getJSONObject("stencil").getString("id"))).findFirst();
            if (startNode.isPresent()) {
                Object node = startNode.get();
                currentResourceId = ((JSONObject) node).getString("resourceId");
            }
        } else {
            currentResourceId = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).taskId(taskId).singleResult().getTaskDefinitionKey();
        }
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(ProcessDefinitionId).singleResult();
        String version = String.valueOf(processDefinition.getVersion());
        XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(xjrNwfScheme.getSchemeInfoId() + StringPool.UNDERSCORE + currentResourceId + StringPool.UNDERSCORE + version, "28");
        String paramInfo = xjrBaseTempfield == null ? null : xjrBaseTempfield.getFvalue();
        JSONArray parameterAssignment = new JSONArray();
        JSONArray processParameters = new JSONArray();
        if (StringUtil.isBlank(taskId)) {
            //将全局参数保存到流程变量中
            String json = xjrNwfScheme.getFjson();
            if (StringUtil.isNotBlank(json)) {
                JSONObject jsonObject = JSONObject.parseObject(json);
                JSONObject properties = jsonObject.getJSONObject("properties");
                processParameters = properties.getJSONArray("parameters");
                for (int i = 0; i < processParameters.size(); i++) {
                    JSONObject processParameter = processParameters.getJSONObject(i);
                    String id = processParameter.getString("id");
                    Object variable = null;
                    if (StringUtil.isNotBlank(processInstanceId)) {
                        variable = runtimeService.getVariable(processInstanceId, id);
                    }
                    String gobalParams = "";
                    if (variable != null) {
                        gobalParams = String.valueOf(variable);
                        paramMap.put(id, gobalParams);
                    } else {
                        try {
                            gobalParams = getGobalParams(xjrNwfSchemeinfo, processParameter, processInstanceId);
                            paramMap.put(id, gobalParams);
                        } catch (Exception e) {
                            log.error(e.getMessage());
                        }
                    }
                }
            }
        }
        if (paramInfo != null) {
            parameterAssignment = JSONObject.parseObject(paramInfo).getJSONArray("parameterAssignment");
            //获取所有流程参数
            String json = xjrNwfScheme.getFjson();
            if (StringUtil.isNotBlank(json)) {
                JSONObject jsonObject = JSONObject.parseObject(json);
                JSONObject properties = jsonObject.getJSONObject("properties");
                processParameters = properties.getJSONArray("parameters");
                for (int i = 0; i < processParameters.size(); i++) {
                    JSONObject processParameter = processParameters.getJSONObject(i);
                    String id = processParameter.getString("id");
                    String value = null;
                    Optional<Object> parameterAssignmentoptional = parameterAssignment.stream().filter(s -> StringUtil.equals(((JSONObject) s).getJSONObject("target").getString("id"), id)).findFirst();
                    if (parameterAssignmentoptional.isPresent()) {
                        Object parameterAssignmenObj = parameterAssignmentoptional.get();
                        JSONObject object = (JSONObject) parameterAssignmenObj;
                        JSONObject source = object.getJSONObject("source");
                        if (StringUtil.isBlank(taskId)) {
                            String type = source.getString("type");
                            if (StringUtil.equals(type, "hideComponents")) {
                                //隐藏组件
                                value = gethideComponentsValue(source);
                            } else {
                                String key = source.getString("resourceId") + StringPool.UNDERSCORE + source.getString("bindTable") + StringPool.UNDERSCORE + source.getString("fieldsId");
                                if (CollectionUtil.isNotEmpty(formValues)) {
                                    value = String.valueOf(formValues.get(key));
                                }
                            }
                        } else {
                            String assignmentType = source.getString("assignmentType");
                            String userId = SecureUtil.getUserId();
                            XjrBaseUser user = userService.getById(userId);
                            if (StringUtil.equals(assignmentType, "variable")) {
                                //变量
                                String type = source.getString("type");
                                if (StringUtil.equals(type, "condition")) {
                                    String key = source.getString("resourceId") + StringPool.UNDERSCORE + source.getString("bindTable") + StringPool.UNDERSCORE + source.getString("fieldsId");
                                    if (CollectionUtil.isNotEmpty(formValues)) {
                                        value = String.valueOf(formValues.get(key));
                                    }
                                } else if (StringUtil.equals(type, "hideComponents")) {
                                    //隐藏组件
                                    value = gethideComponentsValue(source);
                                } else {
                                    value = getProcessInfo(xjrNwfSchemeinfo, processInstanceId, type, source.getString("value"), null);
                                }
                            } else {
                                if (StringUtil.equals(assignmentType, "value")) {
                                    //值
                                    value = source.getString("value");
                                } else if (StringUtil.equals(assignmentType, "sql")) {
                                    //sql
                                    JSONObject taskObj = source.getJSONObject("tasksql");
                                    String database = taskObj.getString("database");
                                    JSONArray templateDatas = taskObj.getJSONArray("templateData");
                                    String sql = "";
                                    for (int j = 0; j < templateDatas.size(); j++) {
                                        JSONObject templateData = templateDatas.getJSONObject(j);
                                        String beforeText = templateData.getString("beforeText");
                                        if (StringUtil.isNotBlank(beforeText)) {
                                            sql = sql + templateData.getString("beforeText");
                                        }
                                        String infoValue = templateData.getString("id");
                                        String infoType = templateData.getString("type");
                                        String resourceId = templateData.getString("resourceId");
                                        String bindTable = templateData.getString("bindTable");
                                        String param = templateData.getString("value");
                                        if (StringUtil.equalsIgnoreCase(infoType, "condition")) {
                                            if (infoValue != null && (!StringUtil.equals("", infoValue))) {
                                                infoValue = resourceId + StringPool.UNDERSCORE + bindTable + StringPool.UNDERSCORE + infoValue;
                                            }
                                        }
                                        if (StringUtil.equalsIgnoreCase(infoType, "hideComponents")) {
                                            param = gethideComponentsValue(templateData);
                                        } else if (infoType != null) {
                                            param = getProcessInfo(xjrNwfSchemeinfo, processInstanceId, infoType, infoValue, null);
                                            if (StringUtil.isBlank(param)) {
                                                Object o = formValues.get(infoValue);
                                                if(o!=null) {
                                                    param = String.valueOf(o);
                                                }
                                            }
                                        }
                                        if (StringUtil.isNotBlank(param)) {
                                            sql = sql + param;
                                        }
                                        String afterText = templateData.getString("afterText");
                                        if (StringUtil.isNotBlank(afterText)) {
                                            sql = sql + afterText;
                                        }
                                    }
                                    String field = taskObj.getString("field");
                                    List<Entity> sqlResult = dbExecutor.executeQuery(database, sql);
                                    if (sqlResult.size() > 0) {
                                        //获取第一条数据
                                        Map<String, Object> firstResult = sqlResult.get(0);
                                        Object o = firstResult.get(field);
                                        if (o != null) {
                                            value = String.valueOf(o);
                                        }
                                    }
                                } else if (StringUtil.equals(assignmentType, "api")) {
                                    JSONObject taskapi = source.getJSONObject("taskapi");
                                    //参数
                                    JSONArray params = taskapi.getJSONArray("params");
                                    //返回的字段
                                    String field = taskapi.getString("field");
                                    String interfaceId = taskapi.getString("interfaceId");
                                    Map<String, String> apiParamMap = new HashMap<>();
                                    HttpServletRequest request = WebUtil.getRequest();
                                    for (int j = 0; j < params.size(); j++) {
                                        JSONObject param = params.getJSONObject(j);
                                        String paramValue = param.getString("paramValue");
                                        String paramName = param.getString("paramName");
                                        //参数值的类型
                                        Integer paramValType = param.getInteger("paramValType");
                                        if (paramValType == 1) {
                                            //变量
                                            if (StringUtil.equals(paramValue, "token")) {
                                                //发起人token
                                                paramValue = request.getHeader("Authorization");
                                            } else if (StringUtil.equals(paramValue, "userid")) {
                                                //发起人id
                                                paramValue = userId;
                                            } else if (StringUtil.equals(paramValue, "username")) {
                                                //发起人名字
                                                paramValue = user.getRealName();
                                            } else if (StringUtil.equals(paramValue, "postid")) {
                                                //发起人岗位id
                                                List<XjrBaseUserRelation> objectsOfUser = userRelationService.getObjectsOfUser(userId, 2);
                                                if (CollectionUtil.isNotEmpty(objectsOfUser)) {
                                                    XjrBaseUserRelation xjrBaseUserRelation = objectsOfUser.get(0);
                                                    paramValue = xjrBaseUserRelation.getObjectId();
                                                }
                                            } else if (StringUtil.equals(paramValue, "companyid")) {
                                                //发起人公司id
                                                paramValue = user.getCompanyId();
                                            } else if (StringUtil.equals(paramValue, "departid")) {
                                                //发起人部门id
                                                List<XjrBaseUserRelation> objectsOfUser = userRelationService.getObjectsOfUser(userId, 3);
                                                if (CollectionUtil.isNotEmpty(objectsOfUser)) {
                                                    XjrBaseUserRelation xjrBaseUserRelation = objectsOfUser.get(0);
                                                    paramValue = xjrBaseUserRelation.getObjectId();
                                                }
                                            } else if (StringUtil.equals(paramValue, "roleid")) {
                                                //发起人角色id
                                                List<XjrBaseUserRelation> objectsOfUser = userRelationService.getObjectsOfUser(userId, 1);
                                                if (CollectionUtil.isNotEmpty(objectsOfUser)) {
                                                    XjrBaseUserRelation xjrBaseUserRelation = objectsOfUser.get(0);
                                                    paramValue = xjrBaseUserRelation.getObjectId();
                                                }
                                            }
                                        }
                                        apiParamMap.put(paramName, paramValue);
                                    }
                                    try {
                                        MediaType JSONType = MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE);
                                        okhttp3.RequestBody body = okhttp3.RequestBody.create(JSONType, JSON.toJSONString(apiParamMap));
                                        String host = serverConfig.getLocalUrl();
                                        String address = host + StringPool.SLASH + "xjr-interface-info" + StringPool.SLASH + "execute" + StringPool.SLASH + interfaceId;
                                        OkHttpClient client = new OkHttpClient();
                                        HttpUrl parse = HttpUrl.parse(address);
                                        HttpUrl.Builder builder = Objects.requireNonNull(parse).newBuilder();
                                        Request.Builder url = new Request.Builder().url(builder.build());
                                        url.addHeader("isWorkFlow", "true");
                                        url.addHeader("Authorization", request.getHeader("Authorization"));
                                        Request req = url.post(body).build();
                                        okhttp3.Response response = client.newCall(req).execute();
                                        if (response.isSuccessful()) {
                                            String responseBody = Objects.requireNonNull(response.body()).string();
                                            JSONObject responseBodyObj = JSONObject.parseObject(responseBody);
                                            if (responseBodyObj.getBoolean("success")) {
                                                JSONObject data = responseBodyObj.getJSONObject("data");
                                                if (CollectionUtil.isNotEmpty(data)) {
                                                    Object o = data.get(field);
                                                    if (o != null) {
                                                        value = String.valueOf(o);
                                                    }
                                                }
                                            }
                                        }
                                    } catch (Exception e) {
                                        log.error(e.getMessage());
                                    }
                                }
                            }
                        }
                        if (StringUtil.isNotBlank(value)) {
                            paramMap.put(processParameter.getString("id"), value);
                        }
                    }
                }
            }
        }
        return paramMap;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/12/29
     * @Param:[processInsId, deployId]
     * @return:void
     * @Description:预处理任务
     */
    private static JSONObject pretreatmentTask(String processInsId, String deployId, String actId) throws Exception {
        JSONObject retObj = new JSONObject();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
        String nwfSchemeInfoId = processDefinition.getDescription();
        XjrNwfScheme xjrNwfScheme = nwfSchemeService.getBySchemeInfoId(nwfSchemeInfoId);
        String json = xjrNwfScheme.getFjson();
        Set<HashMap<String, Object>> node = getUsetTaskNode(actId, processInsId, 1);
        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInsId).singleResult();
        for (HashMap<String, Object> nodeInfo : node) {
            String activityType = nodeInfo.get("activityType").toString();
            String activitiId = nodeInfo.get("activitiId").toString();
            if (StringUtil.equals(activityType, "startEvent")) {
                //获取子流程开始节点发起人
                JSONObject jsonObject = JSONObject.parseObject(json);
                JSONArray childShapes = jsonObject.getJSONArray("childShapes");
                flag:
                for (int i = 0; i < childShapes.size(); i++) {
                    JSONObject childShape = childShapes.getJSONObject(i);
                    JSONArray childShapes1 = childShape.getJSONArray("childShapes");
                    if (CollectionUtil.isNotEmpty(childShapes1)) {
                        for (int j = 0; j < childShapes1.size(); j++) {
                            JSONObject childShape1 = childShapes1.getJSONObject(j);
                            if (StringUtil.equals(childShape1.getString("resourceId"), activitiId)) {
                                String subProcessInitiator = childShape1.getJSONObject("properties").getString("subProcessInitiator");
                                List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInsId).activityId(subProcessInitiator).list();
                                if (CollectionUtil.isNotEmpty(list)) {
                                    HistoricActivityInstance historicActivityInstance = list.get(0);
                                    String assignee = historicActivityInstance.getAssignee();
                                    if (StringUtil.equals(historicActivityInstance.getActivityType(), "startEvent")) {
                                        assignee = processInstance.getStartUserId();
                                    }
                                    nwfTaskMapper.setStartAssigneeByHi(assignee, activitiId, processInsId);
                                    nwfTaskMapper.setStartAssigneeByRun(assignee, activitiId, processInsId);
                                }
                                break flag;
                            }
                        }
                    }
                }
            }
        }
        //下一个节点是外部流程
        Set<String> processInsIds = getCallActivityProcessInsIds(processInsId);
        String superProcessInstanceId = processInstance.getSuperProcessInstanceId();
        if (StringUtil.isNotBlank(superProcessInstanceId)) {
            List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().superProcessInstanceId(superProcessInstanceId).list();
            //添加其他子流程
            if (CollectionUtil.isNotEmpty(processInstanceList)) {
                processInsIds.addAll(processInstanceList.stream().map(s -> s.getProcessInstanceId()).collect(Collectors.toSet()));
            }
        }
        // 1.候选人处理器，判断是否有候选条件和无对应人处理
        retObj = candidateHandler(json, processInsIds);
        // 判断下个任务节点是否有添加候选人，有则将任务指派给用户
        delegateUsers(processInsId, deployId);
        //添加消息给下一个节点审批人
        //开启线程发送消息
        //如果下个节点为空则审批结束,添加审批结束消息
        for (String processInstanceId : processInsIds) {
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery().variableName("initiator").processInstanceId(processInstanceId).singleResult();
            if (variableInstance != null) {
                nwfTaskMapper.setStartUserIdByHi(String.valueOf(variableInstance.getValue()), processInstanceId);
                nwfTaskMapper.setStartAssigneeByHi(String.valueOf(variableInstance.getValue()), historicProcessInstance.getStartActivityId(), processInstanceId);
            }
            deployId = historicProcessInstance.getDeploymentId();
            // 流程模板信息ID
            nwfSchemeInfoId = getNwfSchemeInfoIdByDepId(deployId);
            xjrNwfScheme = nwfSchemeService.getBySchemeInfoId(nwfSchemeInfoId);
            json = xjrNwfScheme.getFjson();
            List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
            if (list.size() == 0) {
                List<HistoricTaskInstance> taskList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInsId).finished().list();
                if (taskList != null && taskList.size() > 0) {
                    java.util.Collections.sort(taskList, (o1, o2) -> o2.getEndTime().compareTo(o1.getEndTime()));
                    HistoricTaskInstance task = taskList.get(0);
                    //发送消息
                    String endActivityId = historicProcessInstance.getEndActivityId();
                    List<Integer> messageTypes = getMessageTypes(endActivityId, json);
                    String startUserId = historicProcessInstance.getStartUserId();
                    ArrayList<String> userIds = new ArrayList<>();
                    userIds.add(startUserId);
                    SendMessageUtil.sendWorkFlowMessage(task, deployId, userIds, 3, messageTypes);
                }
            } else {
                for (Task task : list) {
                    checkManualUser(task, processInsId, deployId);
                    //查找下个节点的消息策略
                    String resourceId = task.getTaskDefinitionKey();
                    List<Integer> messageTypes = getMessageTypes(resourceId, json);
                    ArrayList<String> userIds = nwfTaskMapper.getUserIdByTask(task.getId());
                    if (isMultiInstance(task.getId())) {
                        userIds.add(task.getAssignee());
                    }
                    //获取任务处理人
                    if (CollectionUtil.isNotEmpty(userIds)) {
                        SendMessageUtil.sendWorkFlowMessage(task, deployId, userIds, 1, messageTypes);
                    }
                    retObj.putAll(automaticTask(json, task.getId(), nwfSchemeInfoId, deployId));
                }
            }
        }
        for (String processId : processInsIds) {
            if (StringUtil.equals(processId, processInsId)) {
                Set<String> actIds = getScriptNode(processId, actId);
                scriptTaskHandler(processId, nwfSchemeInfoId, actIds);
            } else {
                HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult();
                deployId = historicProcessInstance.getDeploymentId();
                // 流程模板信息ID
                Set<String> actIds = getScriptNode(processId, null);
                scriptTaskHandler(processId, getNwfSchemeInfoIdByDepId(deployId), actIds);
            }
        }
        return retObj;
    }


    public static Set<String> getCallActivityProcessInsIds(String processInsId) {
        Set<String> processInsIds = new HashSet<>();
        processInsIds.add(processInsId);
        List<ActivityInstance> activityInstanceList = runtimeService.createActivityInstanceQuery().processInstanceId(processInsId).unfinished().list();
        for (ActivityInstance activityInstance : activityInstanceList) {
            if (StringUtil.equals(activityInstance.getActivityType(), "callActivity")) {
                processInsIds.addAll(getCallActivityProcessInsIds(activityInstance.getCalledProcessInstanceId()));
            }
            continue;
        }
        return processInsIds;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2021/1/12
     * @Param:[taskId, nwfSchemeInfoId, processInstanceId, userList, currentUser]
     * @return:com.alibaba.fastjson.JSONObject
     * @Description:无对应处理人
     */
    private static JSONObject noAssigneeHandler(String json, Task task) {
        JSONObject retObj = new JSONObject();
        if (StringUtils.isNotBlank(json)) {
            // 获取无对应处理人的配置
            JSONObject jsonObject = JSON.parseObject(json);
            JSONObject properties = jsonObject.getJSONObject("properties");
            Integer fHandle = properties.getInteger("F_Handle");
            JSONArray userArray = new JSONArray();
            if (fHandle != null && fHandle == 2) {
                retObj.put("userList", userArray);
                retObj.put("taskId", task.getId());
                retObj.put("name", task.getName());
            } else if (fHandle == 1) {
                XjrBaseRole sysRole = roleService.getSysRole();
                List<XjrBaseUser> usersOfObject = userRelationService.getUsersOfObject(sysRole.getRoleId(), 1);
                List<String> userIds = usersOfObject.stream().map(s -> s.getUserId()).collect(Collectors.toList());
                for (String userId : userIds) {
                    taskService.addCandidateUser(task.getId(), userId);
                }
            }
        }
        return retObj;
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2021/2/22
     * @Param:[keyValue, id:nwfSchemeInfoId/taskId]
     * @return:com.alibaba.fastjson.JSONObject
     * @Description:获取表单数据 resourceId_tableName_fieldName
     */
    public static JSONObject getFormData(String keyValue, String taskId, String nwfSchemeInfoId, String deployId) throws SQLException {
        String resourceId = "";
        if (taskId == null) {
            //开始节点
            resourceId = JsonUtil.getStartNodeId(nwfSchemeInfoId);
        } else {
            HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
            resourceId = historicTaskInstance.getTaskDefinitionKey();
        }
        JSONObject formValues = new JSONObject();
        JSONArray jsonArray = JSONArray.parseArray(keyValue);
        if (jsonArray != null) {
            JSONArray customizedFormDatas = new JSONArray();
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject customizedFormDataObj = new JSONObject();
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                String fId = jsonObject.getString("F_Id");
                String formId = jsonObject.getString("F_FormId");
                Map<String, Object> customizedFormData = null;
                Integer type = jsonObject.getInteger("F_Type");
                String urlAddress = jsonObject.getString("F_UrlAddress");
                if (type != null && type == 2) {
                    //系统表单
                    customizedFormData = getSystemFormData(fId, urlAddress);
                } else {
                    //自定义表单z
                    String fFormId = jsonObject.getString("F_FormId");
                    customizedFormData = formSchemeInfoService.getCustomFormData(fFormId, fId);
                }
                customizedFormDataObj.put("formInfo", jsonObject);
                customizedFormDataObj.put("formData", customizedFormData);
                customizedFormDatas.add(customizedFormDataObj);
                //添加当前节点的数据
                formValues.putAll(formData(customizedFormData, resourceId, formId, nwfSchemeInfoId));
                if (StringUtil.isNotBlank(taskId)) {
                    formValues.put(taskId + StringPool.UNDERSCORE + "formData", customizedFormDatas);
                } else {
                    formValues.put(resourceId + StringPool.UNDERSCORE + "formData", customizedFormDatas);
                }
            }
        }
        return formValues;
    }


    public static JSONObject formData(Map<String, Object> customizedFormData, String resourceId, String formId, String nwfSchemeInfoId) throws SQLException {
        XjrNwfScheme nwfScheme = nwfSchemeService.getBySchemeInfoId(nwfSchemeInfoId);
        JSONObject formValues = new JSONObject();
        JSONArray tableDatas = new JSONArray();
        if (nwfScheme != null) {
            JSONObject fjson = JSONObject.parseObject(nwfScheme.getFjson());
            JSONArray childShapes = fjson.getJSONArray("childShapes");
            for (int j = 0; j < childShapes.size(); j++) {
                JSONObject childShape = childShapes.getJSONObject(j);
                if (resourceId.equals(childShape.getString("resourceId"))) {
                    tableDatas = childShape.getJSONObject("properties").getJSONArray("tableData");
                }
            }
        }
        if (customizedFormData != null) {
            Set<Map.Entry<String, Object>> entrySet = customizedFormData.entrySet();
            for (Map.Entry<String, Object> entry : entrySet) {
                // 表名
                String tableName = entry.getKey();
                // 表单数据
                Object object = entry.getValue();
                if (object instanceof HashMap) {
                    // 对象数据类型
                    HashMap record = (HashMap) object;
                    Set<Map.Entry<String, Object>> valueEntrySet = record.entrySet();
                    for (Map.Entry<String, Object> valueEntry : valueEntrySet) {
                        String valueKey = valueEntry.getKey();
                        Object value = valueEntry.getValue();
                        formValues.put(resourceId + StringPool.UNDERSCORE + tableName + StringPool.UNDERSCORE + valueKey, value);
                    }
                } else if (object instanceof ArrayList) {
                    // 数组类型
                    ArrayList array = (ArrayList) object;
                    for (int j = 0; j < array.size(); j++) {
                        Map<String, Object> map = (HashMap) array.get(j);
                        Set<Map.Entry<String, Object>> entrySet1 = map.entrySet();
                        for (Map.Entry<String, Object> entry1 : entrySet1) {
                            String valueKey = entry1.getKey();
                            Object value = entry1.getValue();
                            formValues.put(resourceId + StringPool.UNDERSCORE + tableName + StringPool.UNDERSCORE + valueKey, value);
                        }
                    }
                } else {
                    if (CollectionUtil.isNotEmpty(tableDatas)) {
                        Loop:
                        for (int k = 0; k < tableDatas.size(); k++) {
                            JSONObject tableData = tableDatas.getJSONObject(k);
                            if (formId.equals(tableData.getString("F_Id"))) {
                                JSONArray childrens = tableData.getJSONArray("children");
                                for (int l = 0; l < childrens.size(); l++) {
                                    JSONObject children = childrens.getJSONObject(l);
                                    if (tableName.equals(children.getString("fieldsId"))) {
                                        String bindTable = children.getString("bindTable");
                                        formValues.put(resourceId + StringPool.UNDERSCORE + bindTable + StringPool.UNDERSCORE + tableName, object);
                                        break Loop;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        if (CollectionUtil.isNotEmpty(tableDatas)) {
            //保存隐藏组件的值到流程变量中
            for (int i = 0; i < tableDatas.size(); i++) {
                JSONObject tableData = tableDatas.getJSONObject(i);
                JSONArray hideComponents = tableData.getJSONArray("hideComponents");
                if (CollectionUtil.isNotEmpty(hideComponents)) {
                    for (int j = 0; j < hideComponents.size(); j++) {
                        JSONObject hideComponent = hideComponents.getJSONObject(j);
                        String value = "";
                        String type = hideComponent.getString("type");
                        if (StringUtil.equals(type, "value")) {
                            value = hideComponent.getString("value");
                        }
                        if (StringUtil.equals(type, "sql")) {
                            JSONObject sqlConfig = hideComponent.getJSONObject("sqlConfig");
                            String database = sqlConfig.getString("database");
                            String field = sqlConfig.getString("field");
                            String sql = sqlConfig.getString("sql");
                            List<Map<String, Object>> dataByColumns = databaselinkService.getDataByColumns(database, field, sql);
                            if (CollectionUtil.isNotEmpty(dataByColumns)) {
                                Map<String, Object> map = dataByColumns.get(0);
                                Object o = map.get(field);
                                value = String.valueOf(o);
                            }
                        } else if (StringUtil.equals(type, "api")) {
                            JSONObject apiConfig = hideComponent.getJSONObject("apiConfig");
                            String interfaceId = apiConfig.getString("id");
                            String field = apiConfig.getString("field");
                            JSONArray apiInputParams = apiConfig.getJSONArray("apiInputParams");
                            Map<String, String> paramMap = new HashMap<>();
                            HttpServletRequest request = WebUtil.getRequest();
                            if (CollectionUtil.isNotEmpty(apiInputParams)) {
                                for (int k = 0; k < apiInputParams.size(); k++) {
                                    JSONObject jsonObject = apiInputParams.getJSONObject(k);
                                    paramMap.put(jsonObject.getString("F_ParamKey"), jsonObject.getString("F_ParamValue"));
                                }
                            }
                            try {
                                MediaType JSONType = MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE);
                                okhttp3.RequestBody body = okhttp3.RequestBody.create(JSONType, JSON.toJSONString(paramMap));
                                String host = serverConfig.getLocalUrl();
                                String address = host + StringPool.SLASH + "xjr-interface-info" + StringPool.SLASH + "execute" + StringPool.SLASH + interfaceId;
                                OkHttpClient client = new OkHttpClient();
                                HttpUrl parse = HttpUrl.parse(address);
                                HttpUrl.Builder builder = Objects.requireNonNull(parse).newBuilder();
                                Request.Builder url = new Request.Builder().url(builder.build());
                                url.addHeader("isWorkFlow", "true");
                                url.addHeader("Authorization", request.getHeader("Authorization"));
                                Request req = url.post(body).build();
                                okhttp3.Response response = client.newCall(req).execute();
                                if (response.isSuccessful()) {
                                    String responseBody = Objects.requireNonNull(response.body()).string();
                                    JSONObject responseBodyObj = JSONObject.parseObject(responseBody);
                                    if (responseBodyObj.getBoolean("success")) {
                                        JSONObject data = responseBodyObj.getJSONObject("data");
                                        if (CollectionUtil.isNotEmpty(data)) {
                                            Object o = data.get(field);
                                            if (o != null) {
                                                value = String.valueOf(o);
                                            }
                                        }
                                    }
                                }
                            } catch (Exception e) {
                                log.error(e.getMessage());
                            }
                        }
                       // tableData.getString("F_Id") + hideComponent.getString("id")
                        formValues.put(resourceId + tableData.getString("F_Id") + hideComponent.getString("id"), value);
                    }
                }
            }
        }
        return formValues;
    }


    //外部流程参数输入与输出
    public static JSONObject callActivityParameters(Map<String, Object> customizedFormData, String
            resourceId, String formId, String nwfSchemeInfoId, String processInstanceId) {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        //获取主流程id
        String superProcessInstanceId = historicProcessInstance.getSuperProcessInstanceId();
        Set<JSONObject> targets = new HashSet<>();
        JSONObject result = new JSONObject();
        if (StringUtil.isNotBlank(superProcessInstanceId)) {
            //输入参数
            HistoricProcessInstance superProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(superProcessInstanceId).singleResult();
            ProcessDefinition superProcessDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(superProcessInstance.getProcessDefinitionId()).singleResult();
            String resoucekey = superProcessDefinition.getDescription() + StringPool.UNDERSCORE + resourceId + StringPool.UNDERSCORE + String.valueOf(superProcessDefinition.getVersion());
            List<XjrBaseTempfield> xjrBaseTempfields = xjrBaseTempfieldService.list(Wrappers.<XjrBaseTempfield>query().lambda().eq(XjrBaseTempfield::getFkey, resoucekey).eq(XjrBaseTempfield::getType, "27"));
            for (XjrBaseTempfield xjrBaseTempfield1 : xjrBaseTempfields) {
                String fvalue = xjrBaseTempfield1.getFvalue();
                JSONObject target = JSONObject.parseObject(fvalue);
                targets.add(target);
            }
        } else {
            //输出参数
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(historicProcessInstance.getProcessDefinitionId()).singleResult();
            String resoucekey = processDefinition.getDescription() + StringPool.UNDERSCORE + resourceId + StringPool.UNDERSCORE + String.valueOf(processDefinition.getVersion());
            List<XjrBaseTempfield> xjrBaseTempfields = xjrBaseTempfieldService.list(Wrappers.<XjrBaseTempfield>query().lambda().eq(XjrBaseTempfield::getFkey, resoucekey).eq(XjrBaseTempfield::getType, "29"));
            for (XjrBaseTempfield xjrBaseTempfield1 : xjrBaseTempfields) {
                String fvalue = xjrBaseTempfield1.getFvalue();
                JSONObject target = JSONObject.parseObject(fvalue);
                targets.add(target);
            }
        }
        XjrNwfScheme nwfScheme = nwfSchemeService.getBySchemeInfoId(nwfSchemeInfoId);
        if (customizedFormData == null) {
            if (CollectionUtil.isNotEmpty(targets)) {
                for (JSONObject target : targets) {
                    String key = target.getString("resourceId") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("bindTable") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("fieldsId");
                    String bindTable = target.getString("bindTable");
                    Map<String, Object> valueMap = new HashMap<>();
                    Object o = result.get(bindTable);
                    if (o != null) {
                        valueMap = (Map<String, Object>) o;
                    }
                    HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(key).singleResult();
                    if (historicVariableInstance != null) {
                        Object value = historicVariableInstance.getValue();
                        if (value != null) {
                            String variableTypeName = historicVariableInstance.getVariableTypeName();
//                            if (StringUtil.isNumeric(String.valueOf(value))) {
//                                valueMap.put(target.getString("fieldsId"), Integer.valueOf(String.valueOf(value)));
//                            } else {
                            valueMap.put(target.getString("fieldsId"), value);
//                            }
                        }
                    }
                    if (CollectionUtil.isNotEmpty(valueMap)) {
                        result.put(target.getString("bindTable"), valueMap);
                    }
                }
            }
        } else {
            Set<Map.Entry<String, Object>> entrySet = customizedFormData.entrySet();
            for (Map.Entry<String, Object> entry : entrySet) {
                // 表名
                String tableName = entry.getKey();
                JSONObject tableObj = new JSONObject();
                // 表单数据
                Object object = entry.getValue();
                if (object instanceof HashMap) {
                    // 对象数据类型
                    HashMap record = (HashMap) object;
                    Set<Map.Entry<String, Object>> valueEntrySet = record.entrySet();
                    for (Map.Entry<String, Object> valueEntry : valueEntrySet) {
                        String valueKey = valueEntry.getKey();
                        String key = resourceId + StringPool.UNDERSCORE + tableName + StringPool.UNDERSCORE + valueKey;
                        Optional<JSONObject> targetOption = targets.stream().filter(s -> StringUtil.equals(s.getString("resourceId") + StringPool.UNDERSCORE + s.getString("bindTable") + StringPool.UNDERSCORE + s.getString("fieldsId"), key)).findFirst();
                        if (targetOption.isPresent()) {
                            HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(key).singleResult();
                            if (historicVariableInstance != null) {
                                Object value = historicVariableInstance.getValue();
                                if (value != null) {
//                                    if (StringUtil.isNumeric(String.valueOf(value))) {
//                                        tableObj.put(valueKey, Integer.valueOf(String.valueOf(value)));
//                                    } else {
                                    tableObj.put(valueKey, value);
//                                    }
                                }
                            }
                        }
                    }
                } else if (object instanceof ArrayList) {
                    // 数组类型
                    ArrayList array = (ArrayList) object;
                    for (int j = 0; j < array.size(); j++) {
                        Map<String, Object> map = (HashMap) array.get(j);
                        Set<Map.Entry<String, Object>> entrySet1 = map.entrySet();
                        for (Map.Entry<String, Object> entry1 : entrySet1) {
                            String valueKey = entry1.getKey();
                            String key = resourceId + StringPool.UNDERSCORE + tableName + StringPool.UNDERSCORE + valueKey;
                            Optional<JSONObject> targetOption = targets.stream().filter(s -> StringUtil.equals(s.getString("resourceId") + StringPool.UNDERSCORE + s.getString("bindTable") + StringPool.UNDERSCORE + s.getString("fieldsId"), key)).findFirst();
                            if (targetOption.isPresent()) {
                                HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(key).singleResult();
                                if (historicVariableInstance != null) {
                                    Object value = historicVariableInstance.getValue();
                                    if (value != null) {
//                                        if (StringUtil.isNumeric(String.valueOf(value))) {
//                                            tableObj.put(valueKey, Integer.valueOf(String.valueOf(value)));
//                                        } else {
                                        tableObj.put(valueKey, value);
//                                        }
                                    }
                                }
                            }
                        }
                    }
                } else if (object == null) {
                    if (nwfScheme != null) {
//                        HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
                        JSONObject fjson = JSONObject.parseObject(nwfScheme.getFjson());
                        JSONArray childShapes = fjson.getJSONArray("childShapes");
                        for (int j = 0; j < childShapes.size(); j++) {
                            JSONObject childShape = childShapes.getJSONObject(j);
                            if (resourceId.equals(childShape.getString("resourceId"))) {
                                JSONArray tableDatas = childShape.getJSONObject("properties").getJSONArray("tableData");
                                for (int k = 0; k < tableDatas.size(); k++) {
                                    JSONObject tableData = tableDatas.getJSONObject(k);
                                    if (formId.equals(tableData.getString("F_Id"))) {
                                        JSONArray childrens = tableData.getJSONArray("children");
                                        for (int l = 0; l < childrens.size(); l++) {
                                            JSONObject children = childrens.getJSONObject(l);
                                            String bindTable = children.getString("bindTable");
                                            if (tableName.equals(bindTable)) {
                                                String fieldsId = children.getString("fieldsId");
                                                String key = resourceId + StringPool.UNDERSCORE + bindTable + StringPool.UNDERSCORE + fieldsId;
                                                Optional<JSONObject> targetOption = targets.stream().filter(s -> StringUtil.equals(s.getString("resourceId") + StringPool.UNDERSCORE + s.getString("bindTable") + StringPool.UNDERSCORE + s.getString("fieldsId"), key)).findFirst();
                                                if (targetOption.isPresent()) {
                                                    HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(key).singleResult();
                                                    if (historicVariableInstance != null) {
                                                        Object value = historicVariableInstance.getValue();
                                                        if (value != null) {
//                                                            if (StringUtil.isNumeric(String.valueOf(value))) {
//                                                                tableObj.put(fieldsId, Integer.valueOf(String.valueOf(value)));
//                                                            } else {
                                                            tableObj.put(fieldsId, value);
//                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
//                        if (CollectionUtil.isNotEmpty(objectObjectHashMap)) {
//                            entry.setValue(objectObjectHashMap);
//                        }
                    }
                } else {
                    if (nwfScheme != null) {
                        JSONObject fjson = JSONObject.parseObject(nwfScheme.getFjson());
                        JSONArray childShapes = fjson.getJSONArray("childShapes");
                        Loop:
                        for (int j = 0; j < childShapes.size(); j++) {
                            JSONObject childShape = childShapes.getJSONObject(j);
                            if (resourceId.equals(childShape.getString("resourceId"))) {
                                JSONArray tableDatas = childShape.getJSONObject("properties").getJSONArray("tableData");
                                for (int k = 0; k < tableDatas.size(); k++) {
                                    JSONObject tableData = tableDatas.getJSONObject(k);
                                    if (formId.equals(tableData.getString("F_Id"))) {
                                        JSONArray childrens = tableData.getJSONArray("children");
                                        for (int l = 0; l < childrens.size(); l++) {
                                            JSONObject children = childrens.getJSONObject(l);
                                            if (tableName.equals(children.getString("fieldsId"))) {
                                                String bindTable = children.getString("bindTable");
                                                String key = resourceId + StringPool.UNDERSCORE + bindTable + StringPool.UNDERSCORE + tableName;
                                                Optional<JSONObject> targetOption = targets.stream().filter(s -> StringUtil.equals(s.getString("resourceId") + StringPool.UNDERSCORE + s.getString("bindTable") + StringPool.UNDERSCORE + s.getString("fieldsId"), key)).findFirst();
                                                if (targetOption.isPresent()) {
                                                    HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(key).singleResult();
                                                    if (historicVariableInstance != null) {
                                                        Object value = historicVariableInstance.getValue();
                                                        if (value != null) {
//                                                            if (StringUtil.isNumeric(String.valueOf(value))) {
//                                                                tableObj.put(entry.getKey(), Integer.valueOf(String.valueOf(value)));
//                                                            } else {
                                                            tableObj.put(entry.getKey(), value);
//                                                            }
                                                        }
                                                    }
                                                }
                                                break Loop;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                if (tableObj != null && CollectionUtil.isNotEmpty(tableObj)) {
                    result.put(tableName, tableObj);
                }
            }
        }
        return result;
    }


    //流程参数
    public static JSONObject processParameters(Map<String, Object> customizedFormData, String
            resourceId, String formId, String nwfSchemeInfoId, String processInstanceId, JSONObject parameterValue) {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(historicProcessInstance.getDeploymentId()).singleResult();
        XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(nwfSchemeInfoId + StringPool.UNDERSCORE + resourceId + StringPool.UNDERSCORE + String.valueOf(processDefinition.getVersion()), "28");
        String paramInfo = xjrBaseTempfield != null ? xjrBaseTempfield.getFvalue() : "";
        JSONArray formAssignment = new JSONArray();
        if (StringUtil.isNotBlank(paramInfo)) {
            JSONObject jsonObject = JSONObject.parseObject(paramInfo);
            formAssignment = jsonObject.getJSONArray("formAssignment");
        }
        XjrNwfScheme nwfScheme = nwfSchemeService.getBySchemeInfoId(nwfSchemeInfoId);
        if (customizedFormData == null) {
            if (CollectionUtil.isNotEmpty(formAssignment)) {
                for (int i = 0; i < formAssignment.size(); i++) {
                    JSONObject jsonObject = formAssignment.getJSONObject(i);
                    JSONObject target = jsonObject.getJSONObject("target");
                    JSONObject source = jsonObject.getJSONObject("source");
                    String bindTable = target.getString("bindTable");
                    Map<String, Object> valueMap = new HashMap<>();
                    HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(source.getString("id")).singleResult();
                    if (variableInstance != null) {
                        Object value = variableInstance.getValue();
                        if (value != null) {
//                            if (StringUtil.isNumeric(String.valueOf(value))) {
//                                valueMap.put(target.getString("fieldsId"), Integer.valueOf(String.valueOf(value)));
//                            } else {
                            valueMap.put(target.getString("fieldsId"), value);
//                            }
                        }
                    }
                    JSONObject tableObj = parameterValue.getJSONObject(bindTable);
                    if (tableObj != null) {
                        tableObj.putAll(valueMap);
                    } else {
                        parameterValue.put(bindTable, valueMap);
                    }
                }
            }
        } else {
            Set<Map.Entry<String, Object>> entrySet = customizedFormData.entrySet();
            for (Map.Entry<String, Object> entry : entrySet) {
                // 表名
                String tableName = entry.getKey();
                JSONObject tableObj = parameterValue.getJSONObject(tableName);
                if (tableObj == null) {
                    tableObj = new JSONObject();
                }
                // 表单数据
                Object object = entry.getValue();
                if (object instanceof HashMap) {
                    // 对象数据类型
                    HashMap record = (HashMap) object;
                    Set<Map.Entry<String, Object>> valueEntrySet = record.entrySet();
                    for (Map.Entry<String, Object> valueEntry : valueEntrySet) {
                        String valueKey = valueEntry.getKey();
                        String key = resourceId + StringPool.UNDERSCORE + tableName + StringPool.UNDERSCORE + valueKey;
                        if (CollectionUtil.isNotEmpty(formAssignment)) {
                            for (int i = 0; i < formAssignment.size(); i++) {
                                JSONObject jsonObject = formAssignment.getJSONObject(i);
                                JSONObject target = jsonObject.getJSONObject("target");
                                if (StringUtil.equals(key, target.getString("resourceId") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("bindTable") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("fieldsId"))) {
                                    JSONObject source = jsonObject.getJSONObject("source");
                                    HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(source.getString("id")).singleResult();
                                    if (variableInstance != null) {
                                        Object value = variableInstance.getValue();
                                        if (value != null) {
//                                            if (StringUtil.isNumeric(String.valueOf(value))) {
//                                                tableObj.put(valueKey, Integer.valueOf(String.valueOf(value)));
//                                            } else {
                                            tableObj.put(valueKey, value);
//                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else if (object instanceof ArrayList) {
                    // 数组类型
                    ArrayList array = (ArrayList) object;
                    for (int j = 0; j < array.size(); j++) {
                        Map<String, Object> map = (HashMap) array.get(j);
                        Set<Map.Entry<String, Object>> entrySet1 = map.entrySet();
                        for (Map.Entry<String, Object> entry1 : entrySet1) {
                            String valueKey = entry1.getKey();
                            String key = resourceId + StringPool.UNDERSCORE + tableName + StringPool.UNDERSCORE + valueKey;
                            if (CollectionUtil.isNotEmpty(formAssignment)) {
                                for (int i = 0; i < formAssignment.size(); i++) {
                                    JSONObject jsonObject = formAssignment.getJSONObject(i);
                                    JSONObject target = jsonObject.getJSONObject("target");
                                    if (StringUtil.equals(key, target.getString("resourceId") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("bindTable") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("fieldsId"))) {
                                        JSONObject source = jsonObject.getJSONObject("source");
                                        HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(source.getString("id")).singleResult();
                                        if (variableInstance != null) {
                                            Object value = variableInstance.getValue();
                                            if (value != null) {
//                                                if (StringUtil.isNumeric(String.valueOf(value))) {
//                                                    tableObj.put(valueKey, Integer.valueOf(String.valueOf(value)));
//                                                } else {
                                                tableObj.put(valueKey, value);
//                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else if (object == null) {
                    if (nwfScheme != null) {
                        JSONObject fjson = JSONObject.parseObject(nwfScheme.getFjson());
                        JSONArray childShapes = fjson.getJSONArray("childShapes");
                        for (int j = 0; j < childShapes.size(); j++) {
                            JSONObject childShape = childShapes.getJSONObject(j);
                            if (resourceId.equals(childShape.getString("resourceId"))) {
                                JSONArray tableDatas = childShape.getJSONObject("properties").getJSONArray("tableData");
                                for (int k = 0; k < tableDatas.size(); k++) {
                                    JSONObject tableData = tableDatas.getJSONObject(k);
                                    if (formId.equals(tableData.getString("F_Id"))) {
                                        JSONArray childrens = tableData.getJSONArray("children");
                                        for (int l = 0; l < childrens.size(); l++) {
                                            JSONObject children = childrens.getJSONObject(l);
                                            String bindTable = children.getString("bindTable");
                                            if (tableName.equals(bindTable)) {
                                                String fieldsId = children.getString("fieldsId");
                                                String key = resourceId + StringPool.UNDERSCORE + bindTable + StringPool.UNDERSCORE + fieldsId;
                                                if (CollectionUtil.isNotEmpty(formAssignment)) {
                                                    for (int i = 0; i < formAssignment.size(); i++) {
                                                        JSONObject jsonObject = formAssignment.getJSONObject(i);
                                                        JSONObject target = jsonObject.getJSONObject("target");
                                                        if (StringUtil.equals(key, target.getString("resourceId") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("bindTable") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("fieldsId"))) {
                                                            JSONObject source = jsonObject.getJSONObject("source");
                                                            HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(source.getString("id")).singleResult();
                                                            if (variableInstance != null) {
                                                                Object value = variableInstance.getValue();
                                                                if (value != null) {
//                                                                    if (StringUtil.isNumeric(String.valueOf(value))) {
//                                                                        tableObj.put(fieldsId, Integer.valueOf(String.valueOf(value)));
//                                                                    } else {
                                                                    tableObj.put(fieldsId, value);
//                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
//                        if (CollectionUtil.isNotEmpty(objectObjectHashMap)) {
//                            entry.setValue(objectObjectHashMap);
//                        }
                    }
                } else {
                    if (nwfScheme != null) {
                        JSONObject fjson = JSONObject.parseObject(nwfScheme.getFjson());
                        JSONArray childShapes = fjson.getJSONArray("childShapes");
                        Loop:
                        for (int j = 0; j < childShapes.size(); j++) {
                            JSONObject childShape = childShapes.getJSONObject(j);
                            if (resourceId.equals(childShape.getString("resourceId"))) {
                                JSONArray tableDatas = childShape.getJSONObject("properties").getJSONArray("tableData");
                                for (int k = 0; k < tableDatas.size(); k++) {
                                    JSONObject tableData = tableDatas.getJSONObject(k);
                                    if (formId.equals(tableData.getString("F_Id"))) {
                                        JSONArray childrens = tableData.getJSONArray("children");
                                        for (int l = 0; l < childrens.size(); l++) {
                                            JSONObject children = childrens.getJSONObject(l);
                                            if (tableName.equals(children.getString("fieldsId"))) {
                                                String bindTable = children.getString("bindTable");
                                                String key = resourceId + StringPool.UNDERSCORE + bindTable + StringPool.UNDERSCORE + tableName;
                                                if (CollectionUtil.isNotEmpty(formAssignment)) {
                                                    for (int i = 0; i < formAssignment.size(); i++) {
                                                        JSONObject jsonObject = formAssignment.getJSONObject(i);
                                                        JSONObject target = jsonObject.getJSONObject("target");
                                                        if (StringUtil.equals(key, target.getString("resourceId") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("bindTable") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("fieldsId"))) {
                                                            JSONObject source = jsonObject.getJSONObject("source");
                                                            HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(source.getString("id")).singleResult();
                                                            if (variableInstance != null) {
                                                                Object value = variableInstance.getValue();
                                                                if (value != null) {
//                                                                    if (StringUtil.isNumeric(String.valueOf(value))) {
//                                                                        tableObj.put(entry.getKey(), Integer.valueOf(String.valueOf(value)));
//                                                                        tableName = target.getString("bindTable");
//                                                                    } else {
                                                                    tableObj.put(entry.getKey(), value);
                                                                    tableName = target.getString("bindTable");
//                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                                break Loop;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                if (tableObj != null && CollectionUtil.isNotEmpty(tableObj)) {
                    if (parameterValue.containsKey(tableName)) {
                        JSONObject jsonObject = parameterValue.getJSONObject(tableName);
                        jsonObject.putAll(tableObj);
                        parameterValue.put(tableName, jsonObject);
                    } else {
                        parameterValue.put(tableName, tableObj);
                    }
                }
            }
        }
        return parameterValue;
    }

    //获取全局参数的值
    public static String getGobalParams(XjrNwfSchemeinfo xjrNwfSchemeinfo, JSONObject jsonObject, String
            processInstanceId) throws Exception {
        //模板信息
        String value = "";
        String type = jsonObject.getString("type");
        JSONObject info = jsonObject.getJSONObject("info");
        String userId = SecureUtil.getUserId();
        XjrBaseUser user = userService.getById(userId);
        if (StringUtil.equals(type, "value")) {
            //值
            value = info.getJSONObject("taskvalue").getString("value");
        } else if (StringUtil.equals(type, "variable")) {
            //变量
            JSONArray iframeDatas = info.getJSONObject("taskvariable").getJSONArray("iframeData");
            for (int i = 0; i < iframeDatas.size(); i++) {
                JSONObject iframeData = iframeDatas.getJSONObject(i);
                String variableType = iframeData.getString("type");
                String id = iframeData.getString("id");
                value = value + getProcessInfo(xjrNwfSchemeinfo, processInstanceId, variableType, id, null);
            }
        } else if (StringUtil.equals(type, "sql")) {
            //sql
            JSONObject tasksql = info.getJSONObject("tasksql");
            String database = tasksql.getString("database");
            String sql = tasksql.getString("sql");
            String field = tasksql.getString("field");
            List<Entity> sqlResult = dbExecutor.executeQuery(database, sql);
            if (sqlResult.size() > 0) {
                //获取第一条数据
                Map<String, Object> firstResult = sqlResult.get(0);
                Object o = firstResult.get(field);
                if (o != null) {
                    value = String.valueOf(o);
                }
            }
        } else if (StringUtil.equals(type, "api")) {
            JSONObject taskapi = info.getJSONObject("taskapi");
            //参数
            JSONArray params = taskapi.getJSONArray("params");
            //返回的字段
            String field = taskapi.getString("field");
            String interfaceId = taskapi.getString("interfaceId");
            Map<String, String> paramMap = new HashMap<>();
            HttpServletRequest request = WebUtil.getRequest();
            for (int i = 0; i < params.size(); i++) {
                JSONObject param = params.getJSONObject(i);
                String paramValue = param.getString("paramValue");
                String paramName = param.getString("paramName");
                //参数值的类型
                Integer paramValType = param.getInteger("paramValType");
                if (paramValType == 1) {
                    //变量
                    if (StringUtil.equals(paramValue, "token")) {
                        //发起人token
                        paramValue = request.getHeader("Authorization");
                    } else if (StringUtil.equals(paramValue, "userid")) {
                        //发起人id
                        paramValue = userId;
                    } else if (StringUtil.equals(paramValue, "username")) {
                        //发起人名字
                        paramValue = user.getRealName();
                    } else if (StringUtil.equals(paramValue, "postid")) {
                        //发起人岗位id
                        List<XjrBaseUserRelation> objectsOfUser = userRelationService.getObjectsOfUser(userId, 2);
                        if (CollectionUtil.isNotEmpty(objectsOfUser)) {
                            XjrBaseUserRelation xjrBaseUserRelation = objectsOfUser.get(0);
                            paramValue = xjrBaseUserRelation.getObjectId();
                        }
                    } else if (StringUtil.equals(paramValue, "companyid")) {
                        //发起人公司id
                        paramValue = user.getCompanyId();
                    } else if (StringUtil.equals(paramValue, "departid")) {
                        //发起人部门id
                        List<XjrBaseUserRelation> objectsOfUser = userRelationService.getObjectsOfUser(userId, 3);
                        if (CollectionUtil.isNotEmpty(objectsOfUser)) {
                            XjrBaseUserRelation xjrBaseUserRelation = objectsOfUser.get(0);
                            paramValue = xjrBaseUserRelation.getObjectId();
                        }
                    } else if (StringUtil.equals(paramValue, "roleid")) {
                        //发起人角色id
                        List<XjrBaseUserRelation> objectsOfUser = userRelationService.getObjectsOfUser(userId, 1);
                        if (CollectionUtil.isNotEmpty(objectsOfUser)) {
                            XjrBaseUserRelation xjrBaseUserRelation = objectsOfUser.get(0);
                            paramValue = xjrBaseUserRelation.getObjectId();
                        }
                    }
                }
                paramMap.put(paramName, paramValue);
            }
            MediaType JSONType = MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE);
            okhttp3.RequestBody body = okhttp3.RequestBody.create(JSONType, JSON.toJSONString(paramMap));
            String host = serverConfig.getLocalUrl();
            String address = host + StringPool.SLASH + "xjr-interface-info" + StringPool.SLASH + "execute" + StringPool.SLASH + interfaceId;
            OkHttpClient client = new OkHttpClient();
            HttpUrl parse = HttpUrl.parse(address);
            HttpUrl.Builder builder = Objects.requireNonNull(parse).newBuilder();
            Request.Builder url = new Request.Builder().url(builder.build());
            url.addHeader("isWorkFlow", "true");
            url.addHeader("Authorization", request.getHeader("Authorization"));
            Request req = url.post(body).build();
            okhttp3.Response response = client.newCall(req).execute();
            if (response.isSuccessful()) {
                String responseBody = Objects.requireNonNull(response.body()).string();
                JSONObject responseBodyObj = JSONObject.parseObject(responseBody);
                if (responseBodyObj.getBoolean("success")) {
                    JSONObject data = responseBodyObj.getJSONObject("data");
                    if (CollectionUtil.isNotEmpty(data)) {
                        Object o = data.get(field);
                        if (o != null) {
                            value = String.valueOf(o);
                        }
                    }
                }
            }
//            Response execute = infoService.execute(interfaceId, paramMap, request);
//            if (!execute.isSuccess()) {
//                throw new Exception(execute.getMsg());
//            }
//            if (CollectionUtil.isNotEmpty(result)) {
//                Object o = result.get(field);
//                if (o != null) {
//                    value = String.valueOf(o);
//                }
//            }
        }
        return value;
    }

    public static Map<String, Object> getSystemFormData(String keyValue, String urlAddress) {
        String getDataUrl = StringUtils.endsWith(urlAddress, "/") ? urlAddress + keyValue : urlAddress + StringPool.SLASH + keyValue;
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", SecureUtil.getHeader());
        headers.set("isWorkFlow", "true");
        HttpEntity httpEntity = new HttpEntity<Map>(null, headers);
        Map<String, Object> data = new HashMap<>();
        try {
            ResponseEntity<Map> responseEntity = restTemplate.exchange(serverConfig.getLocalUrl() + StringPool.SLASH + getDataUrl, HttpMethod.GET, httpEntity, Map.class);
            Map<String, Object> body = responseEntity.getBody();
            data = (Map<String, Object>) body.get("data");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return data;
    }


    public static Object updateSystemFormData(String keyValue, String urlAddress, JSONObject formData) {
        String getDataUrl = StringUtils.endsWith(urlAddress, "/") ? urlAddress + keyValue : urlAddress + StringPool.SLASH + keyValue;
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", SecureUtil.getHeader());
        headers.set("isWorkFlow", "true");
        //处理formdata
        JSONObject newFormData = new JSONObject();
        Set<Map.Entry<String, Object>> entries = formData.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value instanceof Map) {
                key = key + "Entity";
            } else if (value instanceof List) {
                key = key + "EntityList";
            }
            newFormData.put(key, value);
        }
        HttpEntity httpEntity = new HttpEntity<Map>(newFormData, headers);
        ResponseEntity<Map> responseEntity = restTemplate.exchange(serverConfig.getLocalUrl() +StringPool.SLASH + getDataUrl, HttpMethod.PUT, httpEntity, Map.class);
        Map<String, Object> body = responseEntity.getBody();
        return body.get("data");
    }


    public static Map<String, Object> deleteSystemFormData(String keyValue, String urlAddress) {
        String getDataUrl = StringUtils.endsWith(urlAddress, "/") ? urlAddress + keyValue : urlAddress + StringPool.SLASH + keyValue;
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", SecureUtil.getHeader());
        HttpEntity httpEntity = new HttpEntity<Map>(null, headers);
        ResponseEntity<Map> responseEntity = restTemplate.exchange(serverConfig.getLocalUrl() + getDataUrl, HttpMethod.DELETE, httpEntity, Map.class);
        Map<String, Object> body = responseEntity.getBody();
        return (Map<String, Object>) body.get("data");
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/23
     * @Param:[processInstanceId, deploymentId]
     * @return:void
     * @Description:判断当前任务是否有传阅人
     */
    public static void checkManualUser(Task task, String processInstanceId, String deploymentId) throws
            Exception {
        String nwfSchemeInfoId = "";
        String version = getVersionByDepId(deploymentId);
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (processInstance != null) {
            String processDefinitionId = processInstance.getProcessDefinitionId();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
            if (processDefinition != null) {
                nwfSchemeInfoId = processDefinition.getDescription();
            }
        }
        // 获取当前任务的节点
        String resourceId = task.getTaskDefinitionKey();
        String key = nwfSchemeInfoId + "_" + resourceId + "_" + version;
        XjrBaseTempfield xjrTempKeyvalue = xjrBaseTempfieldService.getByIdAndType(key, "7");
        if (xjrTempKeyvalue != null) {
            String colValue = xjrTempKeyvalue.getFvalue();
            saveManualInfo(task.getId(), colValue);
        }
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/23
     * @Param:[taskId, forwarderList]
     * @return:void
     * @Description:保存传阅任务信息
     */
    public static void saveManualInfo(String taskId, String forwarderList) throws Exception {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task != null) {
            // 先删除之前的传阅任务
            List<Task> subTaskList = selectSubTask(taskId);
            List<String> taskIds = subTaskList.stream().map(s -> s.getId()).collect(Collectors.toList());
            taskService.deleteTasks(taskIds);
            // 任务表单
            String formKey = task.getFormKey();
            // 节点ID
            String resourceId = task.getTaskDefinitionKey();
            String processInstanceId = task.getProcessInstanceId();
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            String processDefinitionId = processInstance.getProcessDefinitionId();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
            String nwfSchemeInfoId = processDefinition.getDescription();
            String deploymentId = processInstance.getDeploymentId();
            String version = getVersionByDepId(deploymentId);
            // 查询tempkeyValue表
            String key = nwfSchemeInfoId + "_" + resourceId + "_" + version;
            XjrBaseTempfield xjrTempKeyvalue = xjrBaseTempfieldService.getByIdAndType(key, "7");
            boolean isNull = StringUtils.isBlank(forwarderList);
            if (xjrTempKeyvalue != null) {
                // 更新temp表的数据
                // 更新xjr_temp表数据
                xjrTempKeyvalue.setFvalue(forwarderList);
                xjrBaseTempfieldService.updateById(xjrTempKeyvalue);
            } else if (!isNull && !StringUtils.equals(forwarderList, "[]")) {
                XjrBaseTempfield newXjrTempKeyValue = new XjrBaseTempfield();
                newXjrTempKeyValue.setFkey(key);
                newXjrTempKeyValue.setFvalue(forwarderList);
                newXjrTempKeyValue.setType("7");
                xjrBaseTempfieldService.save(newXjrTempKeyValue);
            }
            // 任务分裂
            createSubTask(taskId, formKey, forwarderList);
        } else {
//			LogKit.info("未找到该任务!");
            throw new Exception();
        }
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/23
     * @Param:[taskId, formKey, forwarderList]
     * @return:void
     * @Description:子任务(传阅任务)的创建
     */
    public static void createSubTask(String taskId, String formKey, String forwarderList) throws Exception {
        // 查询传阅人员
        if (StrUtil.isNotBlank(forwarderList) && CollectionUtil.isNotEmpty(JSONArray.parseArray(forwarderList))) {
            HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
            List<HistoricActivityInstance> histList = historyService.createHistoricActivityInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricActivityInstanceStartTime().asc().list();
            Set<String> userIds = FlowableUtil.checkUsers(taskId, histList, JSONArray.parseArray(forwarderList));
            String deploymentId1 = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult().getDeploymentId();
            for (String userId : userIds) {
                Task subTask = taskService.newTask();
                subTask.setAssignee(userId);
                subTask.setName("传阅任务");
                subTask.setParentTaskId(taskId);
                subTask.setFormKey(formKey);
                taskService.saveTask(subTask);
            }
            // 创建传阅任务并发送消息给传阅人
            //获取消息策略
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId1).singleResult();
            String nwfschemeInfoId = processDefinition.getDescription();
            XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(nwfschemeInfoId);
            XjrNwfScheme xjrNwfScheme = nwfSchemeService.getBySchemeInfoId(xjrNwfSchemeinfo.getId());
            String resourceId = nwfTaskMapper.getResourceIdByHiTask(task.getId());
            List<Integer> messageTypes = getMessageTypes(resourceId, xjrNwfScheme.getFjson());
            //添加传阅消息
            SendMessageUtil.sendWorkFlowMessage(task, deploymentId1, new ArrayList<>(userIds), 2, messageTypes);
        }
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/23
     * @Param:[deploymentId]
     * @return:java.lang.String
     * @Description:读取流程资源
     */
    public static String readResource(String deploymentId) throws Exception {
        String filePath = IoUtil.getProjectPath() + "static" + StringPool.SLASH + "images" + StringPool.SLASH + "flowableFile";
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
        InputStream inputStream = Optional.ofNullable(processDefinition)
                .map(p -> repositoryService.getResourceAsStream(deploymentId, p.getDiagramResourceName()))
                .orElseThrow(() -> new Exception("processDefinition为空!"));
        return IoUtil.saveBit(inputStream, filePath);
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/23
     * @Param:[taskId]
     * @return:java.util.List<org.flowable.task.api.Task>
     * @Description:子任务的查询
     */
    public static List<Task> selectSubTask(String taskId) {
        List<Task> subTasks = taskService.getSubTasks(taskId);
        return subTasks;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/12/28
     * @Param:[processInstanceId, type]
     * @return:java.lang.String
     * @Description:获取节点信息 nwfSchemeInfoId + "_" + resourceId + "_" + version;
     */
    public static String getNodeInfo(String processInstanceId, String deployId, String type) {
        String currentResourceId = "";
        String nwfSchemeInfoId = "";
        // deployId为空, processInstanceId不为空
        if (StringUtils.isBlank(deployId)) {
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            if (processInstance != null) {
                deployId = processInstance.getDeploymentId();
            } else {
                HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
                if (historicProcessInstance != null) {
                    processInstanceId = historicProcessInstance.getId();
                    deployId = historicProcessInstance.getDeploymentId();
                }
            }
            // 获取当前节点id
            List<HistoricTaskInstance> hisList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByHistoricTaskInstanceEndTime().asc().list();
            if (!Collections.isEmpty(hisList)) {
                currentResourceId = hisList.get(0).getTaskDefinitionKey();
            }
            nwfSchemeInfoId = getNwfSchemeInfoIdByDepId(deployId);
        } else {
            nwfSchemeInfoId = getNwfSchemeInfoIdByDepId(deployId);
            // 根据json获取开始节点的resourceId
            XjrNwfScheme xjrNwfScheme = nwfSchemeService.getBySchemeInfoId(nwfSchemeInfoId);
            if (xjrNwfScheme != null) {
                JSONObject jsonObject = JSON.parseObject(xjrNwfScheme.getFjson());
                JSONArray childShapes = jsonObject.getJSONArray("childShapes");
                Optional<Object> startNode = childShapes.stream().filter(s -> "StartNoneEvent".equals(((JSONObject) s).getJSONObject("stencil").getString("id"))).findFirst();
                if (startNode.isPresent()) {
                    Object node = startNode.get();
                    currentResourceId = ((JSONObject) node).getString("resourceId");
                }
            }
//                currentResourceId = jsonObject.getJSONArray("childShapes").getJSONObject(0).getString("resourceId");
        }
        // 获取流程版本
        String version = getVersionByDepId(deployId);
        // 获取当前节点的resourceId
        // 查询节点信息
        String key = nwfSchemeInfoId + StringPool.UNDERSCORE + currentResourceId + StringPool.UNDERSCORE + version;
        XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(key, type);
        return xjrBaseTempfield == null ? null : xjrBaseTempfield.getFvalue();
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/23
     * @Param:[deploymentId]
     * @return:java.lang.String
     * @Description:根据部署ID找流程定义version
     */
    public static String getVersionByDepId(String deploymentId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
        return processDefinition != null ? String.valueOf(processDefinition.getVersion()) : null;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/23
     * @Param:[businessKey, currentUser, version, deployId, message]
     * @return:void
     * @Description:驳回到任意节点
     */
    public static void revoke(String businessKey, String currentUser, String version, String deployId, String
            message) throws Exception {
        Task task = taskService.createTaskQuery().processInstanceBusinessKey(businessKey).singleResult();
        if (task == null) {
            throw new Exception("流程未启动或已执行完成，无法撤回");
        }
        // 查历史任务
        List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceBusinessKey(businessKey).orderByTaskCreateTime().asc().list();
        String myTaskId = null;
        HistoricTaskInstance myTask = null;
        String key = deployId + "_" + version + "_" + currentUser;
        // 根据key查询驳回后节点的候选人
        XjrBaseTempfield xjrTempKeyvalue = xjrBaseTempfieldService.getByIdAndType(key, "6");
        String value = xjrTempKeyvalue.getFvalue();
        String loginUser = "";
        if (!StringUtils.isBlank(value)) {
            String replace = value.replace("[", "").replace("]", "").replaceAll(" ", "");
            String[] split = replace.split(",");
            for (String string : split) {
                for (HistoricTaskInstance hti : htiList) {
                    if (string.equals(hti.getAssignee())) {
                        myTaskId = hti.getId();
                        myTask = hti;
                        loginUser = string;
                        break;
                    }
                }
            }
        }
        if (null == myTaskId) {
//            throw new ServiceException("该任务非当前用户提交，无法撤回");
        }

        String processDefinitionId = myTask.getProcessDefinitionId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        // 变量
        String myActivityId = null;
        // 根据excutionId查询已完成任务
        List<HistoricActivityInstance> haiList = historyService.createHistoricActivityInstanceQuery()
                .executionId(myTask.getExecutionId()).finished().list();
        for (HistoricActivityInstance hai : haiList) {
            if (myTaskId.equals(hai.getTaskId())) {
                myActivityId = hai.getActivityId();
                break;
            }
        }
        FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId);
        Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
        String activityId = execution.getActivityId();
        FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
        // 记录原活动方向
        List<SequenceFlow> oriSequenceFlows = new ArrayList<SequenceFlow>();
        oriSequenceFlows.addAll(flowNode.getOutgoingFlows());
        // 清理活动方向
        flowNode.getOutgoingFlows().clear();
        // 建立新方向
        List<SequenceFlow> newSequenceFlowList = new ArrayList<SequenceFlow>();
        SequenceFlow newSequenceFlow = new SequenceFlow();
        newSequenceFlow.setId("newSequenceFlowId");
        newSequenceFlow.setSourceFlowElement(flowNode);
        newSequenceFlow.setTargetFlowElement(myFlowNode);
        newSequenceFlowList.add(newSequenceFlow);
        flowNode.setOutgoingFlows(newSequenceFlowList);

        Authentication.setAuthenticatedUserId(loginUser);
        taskService.addComment(task.getId(), task.getProcessInstanceId(), message);

        Map<String, Object> currentVariables = new HashMap<String, Object>();
        currentVariables.put("applier", loginUser);
        // 完成任务
        taskService.complete(task.getId(), currentVariables);
        // 恢复原方向
        flowNode.setOutgoingFlows(oriSequenceFlows);
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/23
     * @Param:[modelId]
     * @return:java.lang.String
     * @Description:根据modelId查询部署定义key
     */
    public static String getDefinitionKeyByModelId(String modelId) {
        if (StringUtil.isNotBlank(modelId)) {
            Model model = repositoryService.createModelQuery().modelId(modelId).singleResult();
            String deploymentId = model.getDeploymentId();
            ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
            return definition.getKey();
        } else {
            return null;
        }
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/27
     * @Param:[taskId]
     * @return:java.util.Map<java.lang.String,java.lang.Object>
     * @Description:根据任务ID获取表单提交数据
     */
    public static Map<String, Object> getDataByTaskId(String taskId) {
        Map<String, Object> variables = taskService.getVariables(taskId);
        return variables;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/12/9
     * @Param:[dto]
     * @return:com.xjrsoft.common.page.PageOutput<java.util.Map<java.lang.String,java.lang.Object>>
     * @Description:获取流程的历史版本记录
     */
    public static PageOutput<Map<String, Object>> getHisVersion(GetPageHistoryDto dto) throws Exception {
        List<XjrBaseUser> xjrBaseUserlist = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.USER_LIST_CACHE_KEY);
        Long count = 0L;
        IPage<Map<String, Object>> iPage = new Page<Map<String, Object>>();
        String fId = dto.getId();
        List<Map<String, Object>> retList = new ArrayList<>();
        XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(StringUtil.isNotBlank(fId) ? fId : "");
        if (xjrNwfSchemeinfo != null) {
            String currentDeploymentId = xjrNwfSchemeinfo.getDeploymentId();
            // 根据部署ID查流程定义key
            ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(currentDeploymentId).singleResult();
            if (definition != null) {
                String key = definition.getKey();
                // 查询流程定义列表
                List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).orderByProcessDefinitionVersion().desc().listPage(dto.getLimit() - 1, dto.getSize());
                count = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).count();
                iPage.setTotal(count);
                if (!Collections.isEmpty(list)) {
                    for (ProcessDefinition processDefinition : list) {
                        Map<String, Object> map = new HashMap<String, Object>(16);
                        String deploymentId = processDefinition.getDeploymentId();
                        // 流程部署ID
                        map.put("F_DeploymentId", deploymentId);
                        map.put("F_Xml", FlowableUtil.json2Xml(deploymentId));
                        XjrNwfSchemeinfo nwfSchemeInfo = nwfSchemeInfoService.getById(processDefinition.getDescription());
                        XjrBaseTempfield tempKeyValue = xjrBaseTempfieldService.getByIdAndType(nwfSchemeInfo.getId() + "_" + deploymentId, "30");
                        //模板信息id
                        map.put("F_NwfSchemeInfoId", nwfSchemeInfo == null ? "" : nwfSchemeInfo.getId());
                        // 查询流程部署
                        Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
                        // 创建时间
                        Date deploymentDate = deployment.getDeploymentTime();
                        String createTime = DateUtil.format(deploymentDate, "yyyy-MM-dd HH:mm:ss");
                        map.put("F_CreateDate", createTime);
                        // 版本号
                        map.put("F_version", "V1.0." + processDefinition.getVersion());
                        // 流程模板内容
                        map.put("file", readResource(currentDeploymentId));
                        // 创建人
                        // deployment表中的类别存放创建用户的ID
                        String userId = deployment.getCategory();
                        Optional<XjrBaseUser> xjrBaseUserOptional = xjrBaseUserlist.stream().filter(x -> x.getUserId().equals(userId)).findFirst();
                        if (xjrBaseUserOptional.isPresent()) {
                            map.put("F_CreateUserName", xjrBaseUserOptional.get() != null ? xjrBaseUserOptional.get().getRealName() : "");
                        }
                        // 是否是当前版本号标识
                        if (StringUtils.equals(deploymentId, currentDeploymentId)) {
                            map.put("currentVersion", 1);
                        } else {
                            map.put("currentVersion", 0);
                        }
                        retList.add(map);
                    }
                }
            }
        }
        iPage.setRecords(retList);
        iPage.setTotal(count);
        return ConventPage.getPageOutput(iPage);
    }

    /**
     * 流程任务
     */

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[userId, pnum, psize, keyword, startTime, endTime, nwfSchemeInfoId]
     * @return:java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
     * @Description:传阅任务查询
     */
    public static PageOutput upcomingManualTask(GetPageListDto dto, String userId, String nwfSchemeInfoId) throws
            Exception {
        log.info("【查询当前用户的传阅任务】:" + userId);
        return null;
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[processInstanceId]
     * @return:java.lang.String
     * @Description:获取流程图像，已执行节点和流程线高亮显示
     */
    public static String getProccessImage(String processInstanceId) throws Exception {
        String imgPath = IoUtil.getProjectPath() + "static" + StringPool.SLASH + "images" + StringPool.SLASH + "flowableFile";
        // 获取历史流程实例
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (historicProcessInstance == null) {
            throw new Exception("获取流程实例ID[" + processInstanceId + "]对应的历史流程实例失败！");
        } else {
            // 获取流程定义
            ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                    .getDeployedProcessDefinition(historicProcessInstance.getProcessDefinitionId());
            // 获取流程历史中已执行节点，并按照节点在流程中执行先后顺序排序
            List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
            //获取当前的任务
            Set<HashMap<String, Object>> allNode = new HashSet<>();
            List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
            //获取当前任务之前的任务
            if (CollectionUtil.isNotEmpty(list)) {
                for (Task task : list) {
                    allNode.addAll(getAllNode(task.getTaskDefinitionKey(), processInstanceId, 2, new HashSet<String>()));
                    //添加当前任务信息
                    HashMap<String, Object> nodeInfo = new HashMap<>();
                    nodeInfo.put("activitiId", task.getTaskDefinitionKey());
                    nodeInfo.put("activityName", task.getName());
                    nodeInfo.put("activityType", "userTask");
                    allNode.add(nodeInfo);
                }
            }
            // 已执行的节点ID集合
            List<String> executedActivityIdList = new ArrayList<String>();
            int index = 1;
            // logger.info("获取已经执行的节点ID");
            if (CollectionUtil.isNotEmpty(allNode)) {
                Iterator<HistoricActivityInstance> iterator = historicActivityInstanceList.iterator();
                while (iterator.hasNext()) {
                    HistoricActivityInstance activityInstance = iterator.next();
                    Optional<HashMap<String, Object>> optional = allNode.stream().filter(s -> StringUtil.equals(s.get("activitiId").toString(), activityInstance.getActivityId())).findAny();
                    if (!optional.isPresent()) {
                        iterator.remove();
                    }
                }
            }
            for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
                executedActivityIdList.add(activityInstance.getActivityId());
                System.out.println("第[" + index + "]个已执行节点=" + activityInstance.getActivityId() + " : " + activityInstance.getActivityName());
                index++;
            }
            BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
            // 已执行的线集合
            List<String> flowIds = new ArrayList<String>();
            // 获取流程走过的线 (getHighLightedFlows是下面的方法)
            flowIds = getHighLightedFlows(bpmnModel, processDefinition, historicActivityInstanceList);
            // 获取流程图图像字符流
//            ProcessDiagramGenerator pec = processEngineConfiguration.getProcessDiagramGenerator();
            MyProcessDiagramGenerator pec = new MyProcessDiagramGenerator(1.0);
            // 配置字体
            InputStream imageStream = pec.generateDiagram(bpmnModel, "png", executedActivityIdList, flowIds, "宋体", "微软雅黑", "黑体", processEngineConfiguration.getClassLoader(), 1.0, true);
            // 将流转换为图片
            imgPath = IoUtil.saveBit(imageStream, imgPath);
        }
        return imgPath;
    }


    //获取上一个或下一个用户任务节点 1：下一个 2：上一个
    public static Set<HashMap<String, Object>> getUsetTaskNode(String actId, String processInstanceId, Integer
            type) {
        Set<HashMap<String, Object>> nextNodeInfos = new HashSet<>();
        List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
        if (StringUtil.isNotBlank(actId)) {
            HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
            FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(actId);
            HistoricActivityInstance hai = null;
            Optional<HistoricActivityInstance> first = historicActivityInstances.stream().filter(s -> StringUtil.equals(s.getActivityId(), actId)).findFirst();
            if (first.isPresent()) {
                hai = first.get();
            }
            //子流程
            if (hai != null && "subProcess".equals(hai.getActivityType())) {
                SubProcess subProcess = (SubProcess) flowNode;
                List<FlowElement> flowElements = (List<FlowElement>) subProcess.getFlowElements();
                FlowElement flowElement = flowElements.get(0);
                String id = flowElement.getId();
                List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(hai.getProcessInstanceId()).activityId(id).list();
                if (CollectionUtil.isNotEmpty(list)) {
                    HistoricActivityInstance historicActivityInstance = list.get(0);
                    HashMap<String, Object> nextNodeInfo = new HashMap<>();
                    nextNodeInfo.put("activitiId", historicActivityInstance.getActivityId());
                    nextNodeInfo.put("activityName", historicActivityInstance.getActivityName());
                    nextNodeInfo.put("activityType", historicActivityInstance.getActivityType());
                    nextNodeInfos.add(nextNodeInfo);
                }
            } else {
                List<SequenceFlow> flows = new ArrayList<>();
                if (type == 1) {
                    flows = flowNode.getOutgoingFlows();
                } else {
                    flows = flowNode.getIncomingFlows();
                }
                for (SequenceFlow sequenceFlow : flows) {
                    //当前审批节点
                    // 下一个审批节点
                    FlowElement targetFlow = sequenceFlow.getTargetFlowElement();
                    FlowElement sourceFlow = sequenceFlow.getSourceFlowElement();
                    HistoricActivityInstance historicActivityInstance = null;
                    if (type == 1) {
                        Optional<HistoricActivityInstance> hiActivityOption = historicActivityInstances.stream().filter(s -> StringUtil.equals(s.getActivityId(), targetFlow.getId())).findFirst();
                        if (hiActivityOption.isPresent()) {
                            historicActivityInstance = hiActivityOption.get();
                        }
                    } else {
                        Optional<HistoricActivityInstance> hiActivityOption = historicActivityInstances.stream().filter(s -> StringUtil.equals(s.getActivityId(), sourceFlow.getId())).findFirst();
                        if (hiActivityOption.isPresent()) {
                            historicActivityInstance = hiActivityOption.get();
                        }
                    }
                    //如果为网关则获取下一节点的信息
                    if (historicActivityInstance != null) {
                        String activityType = historicActivityInstance.getActivityType();
                        if ("userTask".equals(activityType) || "endEvent".equals(activityType) || "startEvent".equals(activityType) || "callActivity".equals(activityType)) {
                            HashMap<String, Object> nextNodeInfo = new HashMap<>();
                            nextNodeInfo.put("activitiId", historicActivityInstance.getActivityId());
                            nextNodeInfo.put("activityName", historicActivityInstance.getActivityName());
                            nextNodeInfo.put("activityType", historicActivityInstance.getActivityType());
//                        nextNodeInfo.put("taskId", historicActivityInstance.getTaskId());
                            nextNodeInfos.add(nextNodeInfo);
                        } else {
                            nextNodeInfos.addAll(getUsetTaskNode(historicActivityInstance.getActivityId(), processInstanceId, type));
                        }
                    }
                }
            }
        }
        return nextNodeInfos;
    }


    //获取上一个或下一个外部流程 1：下一个 2：上一个
    public static List<FlowElement> getCallActivityNode(String actId, String processDefinitionId, Integer
            type, List<String> actIds) {
        List<FlowElement> flowElements = new ArrayList<>();
        if (actIds.contains(actId)) {
            return flowElements;
        }
        if (StringUtil.isNotBlank(actId)) {
            actIds.add(actId);
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
            FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(actId);
            List<SequenceFlow> flows = new ArrayList<>();
            if (type == 1) {
                flows = flowNode.getOutgoingFlows();
            } else {
                flows = flowNode.getIncomingFlows();
            }
            for (SequenceFlow sequenceFlow : flows) {
                //当前审批节点
                if (type == 1) {
                    FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
                    if (targetFlowElement.getClass().equals(CallActivity.class)) {
                        flowElements.add(targetFlowElement);
                    } else if (targetFlowElement.getClass().equals(UserTask.class) || targetFlowElement.getClass().equals(SubProcess.class)) {
                        return flowElements;
                    } else {
                        flowElements.addAll(getCallActivityNode(targetFlowElement.getId(), processDefinitionId, type, actIds));
                    }
                } else {
                    FlowElement sourceFlowElement = sequenceFlow.getSourceFlowElement();
                    if (sourceFlowElement.getClass().equals(CallActivity.class)) {
                        flowElements.add(sourceFlowElement);
                    } else {
                        flowElements.addAll(getCallActivityNode(sourceFlowElement.getId(), processDefinitionId, type, actIds));
                    }
                }
            }
        }
        return flowElements;
    }


    //获取该节点之前或之后的所有用户任务节点1：该节点之后 2：该节点之前
    public static Set<HashMap<String, Object>> getAllNode(String actId, String processInstanceId, Integer
            type, Set<String> actIds) {
        if (actIds.contains(actId)) {
            //重复节点
            return null;
        }
        actIds.add(actId);
        Set<HashMap<String, Object>> nextNodeInfos = new HashSet<>();
        List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
        List<HistoricActivityInstance> activityInstances = historyService.createHistoricActivityInstanceQuery().activityId(actId).processInstanceId(processInstanceId).list();
        HistoricActivityInstance nowHistoricActivityInstance = activityInstances.get(0);
        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
       FlowElement flowElement1=  bpmnModel.getFlowElement(actId);
       FlowNode flowNode = (FlowNode) flowElement1;
   //     FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(actId);
        FlowElementsContainer parentContainer = bpmnModel.getFlowElement(actId).getParentContainer();
        if (parentContainer instanceof SubProcess && ((StringUtil.equals(nowHistoricActivityInstance.getActivityType(), "startEvent") && type == 2) || (StringUtil.equals(nowHistoricActivityInstance.getActivityType(), "endEvent") && type == 1))) {
            //子流程的开始节点或结束节点
            flowNode = (SubProcess) parentContainer;
        }
        List<SequenceFlow> flows = new ArrayList<>();
        if (type == 1) {
            flows = flowNode.getOutgoingFlows();
        } else {
            flows = flowNode.getIncomingFlows();
        }
        for (SequenceFlow sequenceFlow : flows) {
            //当前审批节点
            // 下一个审批节点
            FlowElement nextFlow = null;
            HistoricActivityInstance historicActivityInstance = null;
            if (type == 1) {
                nextFlow = sequenceFlow.getTargetFlowElement();
                FlowElement finalNextFlow = nextFlow;
                Optional<HistoricActivityInstance> historicActivityInstanceOptional = historicActivityInstanceList.stream().filter(s -> s.getActivityId().equals(finalNextFlow.getId())).findFirst();
                if (historicActivityInstanceOptional.isPresent()) {
                    historicActivityInstance = historicActivityInstanceOptional.get();
                }
            } else {
                nextFlow = sequenceFlow.getSourceFlowElement();
                FlowElement finalNextFlow1 = nextFlow;
                Optional<HistoricActivityInstance> historicActivityInstanceOptional = historicActivityInstanceList.stream().filter(s -> s.getActivityId().equals(finalNextFlow1.getId())).findFirst();
                if (historicActivityInstanceOptional.isPresent()) {
                    historicActivityInstance = historicActivityInstanceOptional.get();
                }
            }
            //如果为网关则获取下一节点的信息
            if (historicActivityInstance != null) {
                String activityType = historicActivityInstance.getActivityType();
                if ("userTask".equals(activityType) || "endEvent".equals(activityType) || "startEvent".equals(activityType)) {
                    HashMap<String, Object> nextNodeInfo = new HashMap<>();
                    nextNodeInfo.put("activitiId", historicActivityInstance.getActivityId());
                    nextNodeInfo.put("activityName", historicActivityInstance.getActivityName());
                    nextNodeInfo.put("activityType", historicActivityInstance.getActivityType());
                    nextNodeInfos.add(nextNodeInfo);
                }
                if ("subProcess".equals(activityType) && type == 1) {
                    Collection<FlowElement> flowElements = ((SubProcess) nextFlow).getFlowElements();
                    //子流程开始节点
                    Optional<FlowElement> elementOptional = flowElements.stream().filter(s -> s instanceof StartEvent).findFirst();
                    if (elementOptional.isPresent()) {
                        FlowElement flowElement = elementOptional.get();
                        historicActivityInstance = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityId(flowElement.getId()).list().get(0);
                    }
                }
                if ("subProcess".equals(activityType) && type == 2) {
                    Collection<FlowElement> flowElements = ((SubProcess) nextFlow).getFlowElements();
                    //子流程结束节点
                    Optional<FlowElement> elementOptional = flowElements.stream().filter(s -> s instanceof EndEvent).findFirst();
                    if (elementOptional.isPresent()) {
                        FlowElement flowElement = elementOptional.get();
                        historicActivityInstance = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityId(flowElement.getId()).list().get(0);
                    }
                }
                Set<HashMap<String, Object>> allNode = getAllNode(historicActivityInstance.getActivityId(), processInstanceId, type, actIds);
                if (CollectionUtil.isNotEmpty(allNode)) {
                    nextNodeInfos.addAll(allNode);
                }
            }
        }
        return nextNodeInfos;
    }

    //获取该节点之前或之后的所有节点和连线1：该节点之后 2：该节点之前
    public static Set<String> getNode(String actId, String processInstanceId, Integer
            type, Set<String> actIds) {
        if (actIds.contains(actId)) {
            //重复节点
            return null;
        }
        actIds.add(actId);
        Set<String> nextNodeInfos = new HashSet<>();
        List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
        List<HistoricActivityInstance> activityInstances = historyService.createHistoricActivityInstanceQuery().activityId(actId).processInstanceId(processInstanceId).list();
        HistoricActivityInstance nowHistoricActivityInstance = activityInstances.get(0);
        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(actId);
        FlowElementsContainer parentContainer = bpmnModel.getFlowElement(actId).getParentContainer();
        if (parentContainer instanceof SubProcess && ((StringUtil.equals(nowHistoricActivityInstance.getActivityType(), "startEvent") && type == 2) || (StringUtil.equals(nowHistoricActivityInstance.getActivityType(), "endEvent") && type == 1))) {
            //子流程的开始节点或结束节点
            flowNode = (SubProcess) parentContainer;
        }
        List<SequenceFlow> flows = new ArrayList<>();
        if (type == 1) {
            flows = flowNode.getOutgoingFlows();
        } else {
            flows = flowNode.getIncomingFlows();
        }
        for (SequenceFlow sequenceFlow : flows) {
            nextNodeInfos.add(sequenceFlow.getId());
            //当前审批节点
            // 下一个审批节点
            FlowElement nextFlow = null;
            HistoricActivityInstance historicActivityInstance = null;
            if (type == 1) {
                nextFlow = sequenceFlow.getTargetFlowElement();
                FlowElement finalNextFlow = nextFlow;
                Optional<HistoricActivityInstance> historicActivityInstanceOptional = historicActivityInstanceList.stream().filter(s -> s.getActivityId().equals(finalNextFlow.getId())).findFirst();
                if (historicActivityInstanceOptional.isPresent()) {
                    historicActivityInstance = historicActivityInstanceOptional.get();
                }
            } else {
                nextFlow = sequenceFlow.getSourceFlowElement();
                FlowElement finalNextFlow1 = nextFlow;
                Optional<HistoricActivityInstance> historicActivityInstanceOptional = historicActivityInstanceList.stream().filter(s -> s.getActivityId().equals(finalNextFlow1.getId())).findFirst();
                if (historicActivityInstanceOptional.isPresent()) {
                    historicActivityInstance = historicActivityInstanceOptional.get();
                }
            }
            //如果为网关则获取下一节点的信息
            if (historicActivityInstance != null) {
                String activityType = historicActivityInstance.getActivityType();
                nextNodeInfos.add(historicActivityInstance.getActivityId());
                if ("subProcess".equals(activityType) && type == 1) {
                    Collection<FlowElement> flowElements = ((SubProcess) nextFlow).getFlowElements();
                    //子流程开始节点
                    Optional<FlowElement> elementOptional = flowElements.stream().filter(s -> s instanceof StartEvent).findFirst();
                    if (elementOptional.isPresent()) {
                        FlowElement flowElement = elementOptional.get();
                        historicActivityInstance = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityId(flowElement.getId()).list().get(0);
                    }
                }
                if ("subProcess".equals(activityType) && type == 2) {
                    Collection<FlowElement> flowElements = ((SubProcess) nextFlow).getFlowElements();
                    //子流程结束节点
                    Optional<FlowElement> elementOptional = flowElements.stream().filter(s -> s instanceof EndEvent).findFirst();
                    if (elementOptional.isPresent()) {
                        FlowElement flowElement = elementOptional.get();
                        historicActivityInstance = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityId(flowElement.getId()).list().get(0);
                        nextNodeInfos.add(historicActivityInstance.getActivityId());
                    }
                }
                Set<String> allNode = getNode(historicActivityInstance.getActivityId(), processInstanceId, type, actIds);
                if (CollectionUtil.isNotEmpty(allNode)) {
                    nextNodeInfos.addAll(allNode);
                }
            }
        }
        return nextNodeInfos;
    }

    public static boolean isStartNode(String processDefinitionId, String actId) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(actId);
        FlowElementsContainer parentContainer = bpmnModel.getFlowElement(actId).getParentContainer();
        boolean flag = false;
        if (parentContainer instanceof SubProcess) {
            //子流程的开始节点或结束节点
            List<SequenceFlow> flows = flowNode.getIncomingFlows();
            for (SequenceFlow sequenceFlow : flows) {
                FlowElement targetFlowElement = sequenceFlow.getSourceFlowElement();
                if (targetFlowElement instanceof StartEvent) {
                    flag = true;
                }
            }
        }
        return flag;
    }


    //获取脚本任务
    public static Set<String> getScriptNode(String processInstanceId, String actId) {
        Set<String> actIds = new HashSet<>();
        List<HistoricActivityInstance> list = new ArrayList<>();
        if (StringUtil.isNotBlank(actId)) {
            list = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityId(actId).list();
        } else {
            list = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityType("startEvent").list();
        }
        if (CollectionUtil.isEmpty(list)) {
            return actIds;
        }
        Optional<HistoricActivityInstance> optional = list.stream().findFirst();
        if (optional.isPresent()) {
            HistoricActivityInstance hai = optional.get();
            BpmnModel bpmnModel = repositoryService.getBpmnModel(hai.getProcessDefinitionId());
            FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(hai.getActivityId());
            List<SequenceFlow> flows = flowNode.getOutgoingFlows();
            for (SequenceFlow sequenceFlow : flows) {
                //当前审批节点
                // 下一个审批节点
                FlowElement targetFlow = sequenceFlow.getTargetFlowElement();
                List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(hai.getProcessInstanceId()).activityId(targetFlow.getId()).list();
                if (historicActivityInstances != null && historicActivityInstances.size() > 0) {
                    HistoricActivityInstance historicActivityInstance = historicActivityInstances.get(0);
                    //如果为脚本任务则继续获取下一节点的信息
                    if (historicActivityInstance != null) {
                        String activityType = historicActivityInstance.getActivityType();
                        if ("scriptTask".equals(activityType)) {
                            actIds.add(historicActivityInstance.getActivityId());
                            actIds.addAll(getScriptNode(processInstanceId, historicActivityInstance.getActivityId()));
                        } else if ("parallelGateway".equals(activityType) || "exclusiveGateway".equals(activityType)) {
                            actIds.addAll(getScriptNode(processInstanceId, historicActivityInstance.getActivityId()));
                        } else if ("endEvent".equals(activityType)) {
                            //为结束节点则看是否为子流程的结束节点
                            FlowElementsContainer parentContainer = targetFlow.getParentContainer();
                            if (parentContainer != null && parentContainer instanceof SubProcess) {
                                SubProcess subProcess = (SubProcess) parentContainer;
                                String parentId = subProcess.getId();
                                actIds.addAll(getScriptNode(processInstanceId, parentId));
                            }
                        }
                    }
                }
            }
        }
        return actIds;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[bpmnModel, processDefinitionEntity, historicActivityInstances]
     * @return:java.util.List<java.lang.String>
     * @Description:获取高亮flow
     */
    public static List<String> getHighLightedFlows(BpmnModel bpmnModel, ProcessDefinitionEntity
            processDefinitionEntity, List<HistoricActivityInstance> historicActivityInstances) {
        // 24小时制
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 用以保存高亮的线flowId
        List<String> highFlows = new ArrayList<String>();
        for (int i = 0; i < historicActivityInstances.size() - 1; i++) {
            // 对历史流程节点进行遍历
            // 得到节点定义的详细信息
            Object activityImpl = bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i).getActivityId());
            if (activityImpl instanceof SequenceFlow) {
                continue;
            }
            // 用以保存后续开始时间相同的节点
            List<FlowElement> sameStartTimeNodes = new ArrayList<FlowElement>();
            FlowElement sameActivityImpl1 = null;
            // 第一个节点
            HistoricActivityInstance activityImpl_ = historicActivityInstances.get(i);
            HistoricActivityInstance activityImp2;
            for (int k = i + 1; k <= historicActivityInstances.size() - 1; k++) {
                // 后续第1个节点
                activityImp2 = historicActivityInstances.get(k);
                if ("userTask".equals(activityImpl_.getActivityType()) && "userTask".equals(activityImp2.getActivityType()) && df.format(activityImpl_.getStartTime()).equals(df.format(activityImp2.getStartTime()))) {
                    // 都是usertask，且主节点与后续节点的开始时间相同，说明不是真实的后继节点
                } else {
                    // 找到紧跟在后面的一个节点
                    sameActivityImpl1 = bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(k).getActivityId());
                    break;
                }
            }
            // 将后面第一个节点放在时间相同节点的集合里
            sameStartTimeNodes.add(sameActivityImpl1);
            for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {
                // 后续第一个节点
                HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);
                // 后续第二个节点
                HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1);
                // 如果第一个节点和第二个节点开始时间相同保存
                if (df.format(activityImpl1.getStartTime()).equals(df.format(activityImpl2.getStartTime()))) {
                    Object sameActivityImpl2 = bpmnModel.getMainProcess().getFlowElement(activityImpl2.getActivityId());
                    if (!(sameActivityImpl2 instanceof SequenceFlow)) {
                        sameStartTimeNodes.add((FlowNode) sameActivityImpl2);
                    }
                } else {
                    // 有不相同跳出循环
                    break;
                }
            }
            // 取出节点的所有出去的线i
            List<SequenceFlow> pvmTransitions = new ArrayList<>();
            if (activityImpl != null) {
                pvmTransitions = ((FlowNode) activityImpl).getOutgoingFlows();
            }
            // 对所有的线进行遍历
            for (SequenceFlow pvmTransition : pvmTransitions) {
                // 如果取出的线的目标节点存在时间相同的节点里，保存该线的id，进行高亮显示
                Object pvmActivityImpl = bpmnModel.getMainProcess().getFlowElement(pvmTransition.getTargetRef());
                if (!(pvmActivityImpl instanceof SequenceFlow)) {
                    if (sameStartTimeNodes.contains(pvmActivityImpl)) {
                        highFlows.add(pvmTransition.getId());
                    }
                }
            }
        }
        return highFlows;

    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[userId, startTime]
     * @return:java.lang.String
     * @Description:统计今日已办理任务
     */
//    public static String taskDoneToday(String userId, Date startTime) {
//        log.info("【统计用户今日已办理任务的数量:】,用户ID" + userId);
//        long count = historyService.createNativeHistoricActivityInstanceQuery()
//                .sql("SELECT count(RES.ID_) FROM ACT_HI_ACTINST RES WHERE RES.ASSIGNEE_ = #{userId}  AND RES.START_TIME_ >= #{startTime}")
//                .parameter("userId", userId).parameter("startTime", startTime).count();
//        return String.valueOf(count);
//    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[processInstanceId]
     * @return:java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
     * @Description:根据流程实例ID获取审批意见
     */
    public static List<Map<String, Object>> getProcessInstanceComment(String processInstanceId) {
        List<XjrBaseUser> xjrBaseUserlist = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.USER_LIST_CACHE_KEY);
        List<Comment> processInstanceComments = new ArrayList<>();
        List<Comment> actComments = taskService.getProcessInstanceComments(processInstanceId);
        List<Map<String, Object>> commentList = new ArrayList<Map<String, Object>>(10);
        String showapproval = "";
        // 当前节点审批内容的配置信息
        String nodeInfo = getNodeInfo(processInstanceId, null, "5");
        if (StringUtils.isNotBlank(nodeInfo) && !StringUtils.equalsIgnoreCase("null", nodeInfo)) {
            JSONObject nodeInfoMap = JSON.parseObject(nodeInfo);
            showapproval = nodeInfoMap.getString("showapproval");
            // 判断当前任务是否只取最终结果
            processInstanceComments.addAll(actComments);
//            }
        }
        // 流程模板信息ID
        String deploymentId = "";
        String nwfSchemeInfoId = "";
        String processDefinitionId = "";
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        deploymentId = historicProcessInstance.getDeploymentId();
        processDefinitionId = historicProcessInstance.getProcessDefinitionId();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        if (processDefinition != null) {
            nwfSchemeInfoId = processDefinition.getDescription();
        }
        String version = getVersionByDepId(deploymentId);
        for (Comment comment : processInstanceComments) {
            String taskId = comment.getTaskId();
            String taskName = "";
            String taskDefinitionKey = "";
            HistoricTaskInstance hisTask = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
            if (hisTask != null) {
                taskName = hisTask.getName();
                taskDefinitionKey = hisTask.getTaskDefinitionKey();
            }
            String key = nwfSchemeInfoId + StringPool.UNDERSCORE + taskDefinitionKey + StringPool.UNDERSCORE + version;
            //获取按钮信息
            // 当前节点审批内容的配置信息
            XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(key, "2");
            XjrBaseTempfield xjrTempKeyvalue = xjrBaseTempfieldService.getByIdAndType(key, "5");
            if (xjrTempKeyvalue != null) {
                JSONObject value = JSON.parseObject(xjrTempKeyvalue.getFvalue());
                JSONArray approvalcomponents = value.getJSONArray("approvalcomponents");
                flag:
                for (Object approvalcomponent : approvalcomponents) {
                    JSONObject commentMap = new JSONObject();
                    JSONArray jsonArray = new JSONArray();
                    jsonArray.add(approvalcomponent);
                    commentMap.put("taskName", taskName);
                    commentMap.putAll(xjrTempKeyvalue != null ? JSON.parseObject(xjrTempKeyvalue.getFvalue()) : new JSONObject());
                    commentMap.put("approvalcomponents", jsonArray);
                    // 批注ID
                    String id = comment.getId();
                    commentMap.put("id", id);
                    // 批注时间
                    Date time = comment.getTime();
                    String dateFormat = DateUtil.formatDate(time);
                    commentMap.put("time", dateFormat);
                    // 批注内容
                    JSONObject fullMsgMap = JSON.parseObject(comment.getFullMessage());
                    String btnValue = fullMsgMap.getString("btnValue");
                    // 审批按钮的值
                    if (xjrBaseTempfield != null && StringUtil.isNotBlank(xjrBaseTempfield.getFvalue())) {
                        JSONArray btnInfos = JSONArray.parseArray(xjrBaseTempfield.getFvalue());
                        for (int i = 0; i < btnInfos.size(); i++) {
                            JSONObject btnObj = btnInfos.getJSONObject(i);
                            if (StringUtils.equals(btnValue, btnObj.getString("val"))) {
                                btnValue = btnObj.getString("key");
                                break;
                            }
                        }
                    }
                    XjrLgMark lgMarkByCode = lgMarkService.getLgMarkByCode(btnValue);
                    if (lgMarkByCode != null) {
                        btnValue = lgMarkByCode.getName();
                    }
                    fullMsgMap.put("btnValue", btnValue);
                    commentMap.putAll(fullMsgMap);
                    // 批注人
                    String userId = comment.getUserId();
                    Optional<XjrBaseUser> xjrBaseUserOptional = xjrBaseUserlist.stream().filter(x -> x.getUserId().equals(userId)).findFirst();
                    if (xjrBaseUserOptional.isPresent()) {
                        commentMap.put("createUser", xjrBaseUserOptional.get() != null ? xjrBaseUserOptional.get().getRealName() : "");
                    }
                    if (StringUtils.equals(showapproval, "1")) {
                        if (CollectionUtil.isNotEmpty(commentList)) {
                            for (int i = 0; i < commentList.size(); i++) {
                                Map<String, Object> map = commentList.get(i);
                                JSONArray approvalcomponentArray = (JSONArray) (map.get("approvalcomponents"));
                                if (StringUtil.equals(approvalcomponentArray.getString(0), approvalcomponent.toString())) {
                                    continue flag;
                                }
                            }
                        }
                    }
                    commentList.add(commentMap);
                }
            }
        }
        return commentList;
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[taskId, processInstanceId]
     * @return:java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
     * @Description:获取传阅任务信息
     */
    public static List<Map<String, Object>> getManualInfo(String taskId, String processInstanceId) {
        Task task = null;
        List<Map<String, Object>> userList = new ArrayList<>();
        if (StringUtils.isNotBlank(taskId)) {
            task = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (task != null) {
                processInstanceId = task.getProcessInstanceId();
            }
        } else {
            List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
            if (Collections.isEmpty((taskList))) {
                task = taskList.get(0);
            }
        }
        if (task != null) {
            // 节点ID
            String resourceId = task.getTaskDefinitionKey();
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            String processDefinitionId = processInstance.getProcessDefinitionId();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
            String nwfSchemeInfoId = processDefinition.getDescription();
            String deploymentId = processInstance.getDeploymentId();
            String version = getVersionByDepId(deploymentId);
            String key = nwfSchemeInfoId + "_" + resourceId + "_" + version;
            // 查询tempkeyValue表
            XjrBaseTempfield xjrTempKeyvalue = xjrBaseTempfieldService.getByIdAndType(key, "7");
            if (xjrTempKeyvalue != null) {
                String value = xjrTempKeyvalue.getFvalue();
                userList = (List<Map<String, Object>>) JSONObject.parse(value);
            }
        }
        return userList;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[processInstanceId]
     * @return:java.util.List<org.flowable.engine.history.HistoricActivityInstance>
     * @Description:获取流程历史中已执行节点，并按照节点在流程中执行先后顺序排序
     */
    public static JSONObject getFinishedTask(String processInstanceId) {
        // 获取任务key
        JSONObject result = new JSONObject();
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        Set<String> finishedNode = new HashSet<>();
        Set<String> upcomingNode = new HashSet<>();
        if (historicProcessInstance != null && historicProcessInstance.getEndTime() != null) {
            //流程已结束，获取所有节点
            List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceEndTime().asc().list();
            for (HistoricActivityInstance historicActivityInstance : list) {
                finishedNode.add(historicActivityInstance.getActivityId());
            }
        } else {
            List<ActivityInstance> list = runtimeService.createActivityInstanceQuery().processInstanceId(processInstanceId).list();
            String recallActId = "";
            for (int i = list.size() - 1; i >= 0; i--) {
                ActivityInstance activityInstance = list.get(i);
                String deleteReason = activityInstance.getDeleteReason();
                if (StringUtil.isNotBlank(deleteReason)) {
                    //驳回节点
                    String[] to_s = StringUtil.split(deleteReason, "to ");
                    if (to_s != null && to_s.length > 1) {
                        //撤回的节点
                        recallActId = to_s[1];
                        break;
                    }
                }
            }
            Integer startIndex = null;
            Integer endIndex = null;
            //获取开始节点
            for (int i = 0; i < list.size(); i++) {
                ActivityInstance activityInstance = list.get(i);
                String activityId = activityInstance.getActivityId();
                if (StringUtil.equals(activityId, recallActId)) {
                    startIndex = i;
                    break;
                }
            }
            //获取结束节点
            for (int i = list.size() - 1; i >= 0; i--) {
                ActivityInstance activityInstance = list.get(i);
                String activityId = activityInstance.getActivityId();
                if (StringUtil.equals(activityId, recallActId)) {
                    endIndex = i;
                    break;
                }
            }
            //删除驳回节点之间的节点
            if (startIndex != null && endIndex != null) {
                List<ActivityInstance> sub = cn.hutool.core.collection.CollectionUtil.sub(list, 0, startIndex);
                list = cn.hutool.core.collection.CollectionUtil.sub(list, endIndex, list.size());
                list.addAll(sub);
            }
            List<ActivityInstance> unfinishedList = runtimeService.createActivityInstanceQuery().processInstanceId(processInstanceId).unfinished().list();
            if (CollectionUtil.isNotEmpty(unfinishedList)) {
                upcomingNode = unfinishedList.stream().map(s -> s.getActivityId()).collect(Collectors.toSet());
            }
            if (CollectionUtil.isNotEmpty(list)) {
                for (ActivityInstance activityInstance : list) {
                    if (!upcomingNode.contains(activityInstance.getActivityId())) {
                        finishedNode.add(activityInstance.getActivityId());
                    }
                }
            }
        }
        result.put("upcoming", upcomingNode);
        result.put("finished", finishedNode);
        return result;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[processInstanceId]
     * @return:java.lang.String
     * @Description:根据部署id获取nwfSchemeInfoId
     */
    public static String getNwfSchemeInfoIdByDepId(String deployId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
        return processDefinition != null ? String.valueOf(processDefinition.getDescription()) : null;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[nwfSchemeInfoId]
     * @return:java.util.Map<java.lang.String,java.lang.String>
     * @Description:根据nwfSchemeInfoId获取流程配置信息
     */
    public static Map<String, String> getNwfSchemeConfigById(String nwfSchemeInfoId) {
        XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(nwfSchemeInfoId);
        if (xjrNwfSchemeinfo != null) {
            String fConfigurationInfo = xjrNwfSchemeinfo.getConfigurationInfo();
            if (StringUtils.isNotBlank(fConfigurationInfo)) {
                Map<String, String> configMap = (Map<String, String>) JSON.parse(fConfigurationInfo);
                return configMap;
            }
        }
        return null;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[taskId, currentUser, message, targetActivitiId]
     * @return:void
     * @Description:回退到某个节点
     */
    public static void rollBack(String processInstanceId, String targetActivitiId) throws Exception {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (historicProcessInstance == null || historicProcessInstance.getEndTime() != null || "删除".equals(historicProcessInstance.getDeleteReason()) || (processInstance != null && processInstance.isSuspended())) {
            throw new Exception("流程已删除或已结束!!");
        }
        Set<String> currentActivityIds = new TreeSet<>();
        List<ActivityInstance> taskList = runtimeService.createActivityInstanceQuery().processInstanceId(processInstanceId).unfinished().list();
        for (ActivityInstance task : taskList) {
            if (!currentActivityIds.contains(task.getActivityId())) {
                currentActivityIds.add(task.getActivityId());
            }
        }
        runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(processInstanceId).moveActivityIdsToSingleActivityId(new ArrayList<>(currentActivityIds), targetActivitiId).changeState();
        //重新设置审批人
        List<Task> taskList1 = taskService.createTaskQuery().processInstanceId(processInstanceId).taskDefinitionKey(targetActivitiId).list();
        if (StringUtil.equals(targetActivitiId, historicProcessInstance.getStartActivityId())) {
            taskList1 = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        }
        if (CollectionUtil.isNotEmpty(taskList1)) {
            for (Task task : taskList1) {
                Optional<HistoricActivityInstance> historicActivityInstanceOptional = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityId(task.getTaskDefinitionKey()).finished().orderByHistoricActivityInstanceEndTime().desc().list().stream().findFirst();
                if (historicActivityInstanceOptional.isPresent()) {
                    HistoricActivityInstance historicActivityInstance = historicActivityInstanceOptional.get();
                    ArrayList<String> usersIds = nwfTaskMapper.getUserIdByTask(historicActivityInstance.getTaskId());
                    ArrayList<String> userIdByTask = nwfTaskMapper.getUserIdByTask(task.getId());
                    for (String usersId : usersIds) {
                        if (!userIdByTask.contains(usersId)) {
                            taskService.addCandidateUser(task.getId(), usersId);
                        }
                    }
                }
            }
        }
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2021/1/7
     * @Param:[]
     * @return:void
     * @Description:动态添加节点
     */
    public static void addNode() {
        String processInstanceId = "";
        DynamicUserTaskBuilder dynamicUserTaskBuilder = new DynamicUserTaskBuilder();
        dynamicUserTaskBuilder.setId(StringUtil.randomUUID());
        dynamicUserTaskBuilder.setName("tempUserTask");
        dynamicUserTaskBuilder.setAssignee("dd5d4xBrDO");
        bpmnService.injectUserTaskInProcessInstance(processInstanceId, dynamicUserTaskBuilder);
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[taskId, processInstanceId]
     * @return:boolean
     * @Description:判断当前任务是否是会签节点
     */
    public static boolean isMultiInstance(String taskId) {
        HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        if (task != null) {
            BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
            Process process = bpmnModel.getProcesses().get(0);
            // 当前节点
            Map<String, FlowElement> flowElementMap = process.getFlowElementMap();
            FlowElement flowElement = flowElementMap.get(task.getTaskDefinitionKey());
            UserTask currentNode = (UserTask) flowElement;
            if (currentNode != null) {
                Object behavior = currentNode.getBehavior();
                if (behavior instanceof UserTaskActivityBehavior) {
                    return false;
                } else if (behavior instanceof ParallelMultiInstanceBehavior || behavior instanceof SequentialMultiInstanceBehavior) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[taskId, processInstanceId]
     * @return:boolean
     * @Description:判断当前流程是否允许加签
     */
    public static boolean validateSignation(String taskId) {
        HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        if (task != null) {
            String resourceId = task.getTaskDefinitionKey();
            String processDefinitionId = task.getProcessDefinitionId();
            ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
            if (definition != null) {
                // 流程设计模板ID
                String nwfSchemeInfoId = definition.getDescription();
                // 获取json
                JSONObject jsonObject = nwfSchemeService.getSchemeJsonByInfoId(nwfSchemeInfoId);
                if (jsonObject != null) {
                    JSONArray childShapes = jsonObject.getJSONArray("childShapes");
                    if (CollectionUtil.isNotEmpty(childShapes)) {
                        for (int i = 0; i < childShapes.size(); i++) {
                            JSONObject childShape = childShapes.getJSONObject(i);
                            String currentResourceId = childShape.getString("resourceId");
                            if (StringUtils.equals(currentResourceId, resourceId)) {
                                // 获取加签配置
                                JSONObject properties = childShape.getJSONObject("properties");
                                String fksignature = properties.getString("fksignature");
                                if (StringUtils.equals(fksignature, "0")) {
                                    return false;
                                } else {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
        }
        return false;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[taskId, assigneeList, currentUser, processInstanceId]
     * @return:boolean
     * @Description:加签/减签
     */
    public static boolean signature(String taskId, JSONArray assigneeList, XjrUser currentUser) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task != null) {
            // 获取之前的审批人员集合
            String processInstanceId = task.getProcessInstanceId();
            JSONArray oldUserList = getMultiInstanceTaskCandidateUser(processInstanceId);
            if (oldUserList.size() < assigneeList.size()) {
                // 和之前的审批人员集合取差集
                JSONArray differenceList = differenceList(assigneeList, oldUserList);
                for (int i = 0; i < differenceList.size(); i++) {
                    JSONObject map = new JSONObject();
                    JSONObject jsonObject = differenceList.getJSONObject(i);
                    map.put("username", StringUtils.isNotBlank(jsonObject.getString("userId")) ? jsonObject.getString("userId") : jsonObject.getString("F_UserId"));
                    Object variable = taskService.getVariable(taskId, task.getTaskDefinitionKey() + StringPool.UNDERSCORE + "usernamelist");
                    JSONArray jsonArray = JSONArray.parseArray(JSONObject.toJSONString(variable));
                    jsonArray.add(StringUtils.isNotBlank(jsonObject.getString("userId")) ? jsonObject.getString("userId") : jsonObject.getString("F_UserId"));
                    taskService.setVariable(taskId, task.getTaskDefinitionKey() + StringPool.UNDERSCORE + "usernamelist", jsonArray);
                    runtimeService.addMultiInstanceExecution(task.getTaskDefinitionKey(), task.getProcessInstanceId(), map);
                }
                return true;
            } else if (oldUserList.size() > assigneeList.size()) {
                Object variable = taskService.getVariable(taskId, task.getTaskDefinitionKey() + StringPool.UNDERSCORE + "usernamelist");
                JSONArray jsonArray = JSONArray.parseArray(JSONObject.toJSONString(variable));
                Object nrOfInstancesObj = taskService.getVariable(taskId, "nrOfInstances ");
                Integer nrOfInstances = (Integer) nrOfInstancesObj;
                // 获取要减签人员的任务ID
                List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
                // 取两个集合的差集
                JSONArray resultList = differenceList(oldUserList, assigneeList);
                String fUserId = currentUser.getUserId();
                for (int i = 0; i < resultList.size(); i++) {
                    JSONObject jsonObject = resultList.getJSONObject(i);
                    String userId = StringUtils.isNotBlank(jsonObject.getString("userId")) ? jsonObject.getString("userId") : jsonObject.getString("F_UserId");
                    // 不能删除当前登录用户
                    if (!StringUtils.equalsIgnoreCase(userId, fUserId)) {
                        for (Task runTask : list) {
                            String assignee = runTask.getAssignee();
                            if (StringUtils.equals(assignee, userId)) {
                                // 减签
                                runtimeService.deleteMultiInstanceExecution(runTask.getExecutionId(), false);
                            }
                        }
                        if (nrOfInstances > 0) {
                            nrOfInstances = nrOfInstances - 1;
                            jsonArray.remove(userId);
                        }
                    }
                }
                taskService.setVariable(taskId, task.getTaskDefinitionKey() + StringPool.UNDERSCORE + "usernamelist", jsonArray);
                taskService.setVariable(taskId, "nrOfInstances ", nrOfInstances);
                return true;
            } else {
                return true;
            }
        }
        return false;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[biggerList, smallerList]
     * @return:java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
     * @Description:取两个List集合的差集
     */
    private static JSONArray differenceList(JSONArray biggerList, JSONArray smallerList) {
        JSONArray tempList = new JSONArray();
        for (int i = 0; i < smallerList.size(); i++) {
            JSONObject newUserObj = smallerList.getJSONObject(i);
            String newUserId = StringUtils.isNotBlank(newUserObj.getString("userId")) ? newUserObj.getString("userId") : newUserObj.getString("F_UserId");
            for (int j = 0; j < biggerList.size(); j++) {
                JSONObject oldUserObj = biggerList.getJSONObject(j);
                String oldUserId = StringUtils.isNotBlank(oldUserObj.getString("userId")) ? oldUserObj.getString("userId") : oldUserObj.getString("F_UserId");
                if (StringUtils.equalsIgnoreCase(newUserId, oldUserId)) {
                    tempList.add(oldUserObj);
                }
            }
        }
        // 取差集
//        biggerList.removeAll(tempList);
        for (int j = 0; j < tempList.size(); j++) {
            JSONObject tempObj = tempList.getJSONObject(j);
            String newId = StringUtils.isNotBlank(tempObj.getString("userId")) ? tempObj.getString("userId") : tempObj.getString("F_UserId");
            for (int i = 0; i < biggerList.size(); i++) {
                JSONObject otherObj = biggerList.getJSONObject(i);
                String otherId = StringUtils.isNotBlank(otherObj.getString("userId")) ? otherObj.getString("userId") : otherObj.getString("F_UserId");
                if (StringUtils.equals(newId, otherId)) {
                    biggerList.remove(i);
                }
            }
        }
        return biggerList;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[processInstanceId, nwfSchemeInfoId]
     * @return:boolean
     * @Description:判断当前流程是否有任务处理人 false - 无处理人 ;true - 有处理人
     */
//    public static boolean haveAssignee(String processInstanceId, String nwfSchemeInfoId) {
//        boolean flag = true;
//        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
//        if (!Collections.isEmpty(taskList)) {
//            Task task = taskList.get(0);
//            // 任务审批人
//            String assignee = task.getAssignee();
//            // 任务候选人
//            List<HistoricIdentityLink> userList = historyService.getHistoricIdentityLinksForTask(task.getId());
//            for (HistoricIdentityLink historicIdentityLink : userList) {
//                String userId = historicIdentityLink.getUserId();
//                if (StringUtils.isNotBlank(userId)) {
//                    flag = true;
//                    break;
//                }
//            }
//            if (StringUtils.isNotBlank(assignee) || flag) {
//                flag = true;
//            } else {
//                flag = false;
//            }
//        }
//        // 判断开始节点的下一节点是否有处理人
//        if (StringUtils.isNotBlank(nwfSchemeInfoId)) {
//            XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(nwfSchemeInfoId);
//            if (xjrNwfSchemeinfo != null) {
//                String fDeploymentId = xjrNwfSchemeinfo.getDeploymentId();
//                XjrBaseTempfield xjrTempKeyvalue = xjrBaseTempfieldService.getByIdAndType(nwfSchemeInfoId + "_" + fDeploymentId, "3");
//                if (xjrTempKeyvalue != null) {
//                    // json_obj
//                    String colValue = xjrTempKeyvalue.getValue_();
//                    Map<String, Object> jsonMap = (Map<String, Object>) JSON.parse(colValue);
//                    JSONArray childShapes = (JSONArray) jsonMap.get("childShapes");
//                    // 开始节点走向下一个节点的ID
//                    JSONArray startNodeOutgoing = (JSONArray) childShapes.getJSONObject(0).get("outgoing");
//                    // 找到开始节点的下个节点
//                    for (int i = 0; i < startNodeOutgoing.size(); i++) {
//                        JSONObject outgoingObj = startNodeOutgoing.getJSONObject(i);
//                        String resourceId = outgoingObj.getString("resourceId");
////                        boolean haveAssignee = JsonKit.checkNextFlowNodeHaveAssignee(childShapes, resourceId);
////                        if (!haveAssignee) {
////                            flag = false;
////                        }
//                    }
//                }
//            }
//        }
//        return flag;
//    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[taskId, json]
     * @return:boolean
     * @Description:设置任务审批人
     */
//    public static boolean setTaskCandidateUser(String taskId, String json) throws SQLException {
//        List<Task> taskList = taskService.createTaskQuery().taskId(taskId).list();
//        if (!Collections.isEmpty(taskList)) {
//            Task task = taskList.get(0);
//            String processInstanceId = task.getProcessInstanceId();
//            JSONArray userList = JSON.parseArray(json);
//            List<HistoricActivityInstance> histList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
//            checkUsers(taskId, histList, userList, 1);
//        } else {
//            log.info("任务不存在！");
//            return false;
//        }
//        return true;
//    }

//    /**
//     * @Author:湘北智造-框架开发组
//     * @Date:2020/11/3
//     * @Param:[pNum, pSize, keyword, startTime, endTime]
//     * @return:java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
//     * @Description:回收站的查询
//     */
//    public static List<Map<String, Object>> recycleBin(GetPageListDto dto) {
//        String deploymentId = "";
//        String startUserId = "";
//        Date processStartTime = null;
//        String endActivityId = null;
//        List<Map<String, Object>> retList = new ArrayList<>();
//        IPage<XjrBaseTempfield> pageData = xjrBaseTempfieldService.getByType(dto, "18");
//        List<XjrBaseTempfield> tempKeyvalueList = pageData.getRecords();
//        for (XjrBaseTempfield xjrTempKeyvalue : tempKeyvalueList) {
//            Map<String, Object> map = new HashMap<>(16);
//            String processInstanceId = xjrTempKeyvalue.getFkey();
//            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//            if (processInstance != null) {
//                deploymentId = processInstance.getDeploymentId();
//                processStartTime = processInstance.getStartTime();
//            } else {
//                // 查询历史流程实例
//                HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//                deploymentId = historicProcessInstance.getDeploymentId();
//                processStartTime = historicProcessInstance.getStartTime();
//                endActivityId = historicProcessInstance.getEndActivityId();
//            }
//            List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
//            // 判断是否有设置任务命名规则
////            String taskName = taskNameRule(deploymentId, processInstanceId);
//            if (!Collections.isEmpty(taskList)) {
//                // 正在执行的任务
//                Task task = taskList.get(0);
//                map.put("taskName", task.getName());
//                // 等级
//                map.put("priority", task.getPriority());
//                // 任务id
//                String taskId = task.getId();
//                map.put("taskId", taskId);
//            } else {
//                // 历史任务的查询
//                // 历史任务的查询
//                List<HistoricActivityInstance> hisProcessInstanceList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
//                HistoricActivityInstance hisProcessInstance = hisProcessInstanceList.get(hisProcessInstanceList.size() - 1);
//                List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).list();
//                HistoricTaskInstance historicTaskInstance = historicTaskInstanceList.get(historicTaskInstanceList.size() - 1);
//                // 任务
//                map.put("taskName", StringUtils.isBlank(hisProcessInstance.getActivityName()));
//                // 等级
//                map.put("priority", historicTaskInstance.getPriority());
//                // 任务id
//                String taskId = historicTaskInstance.getId();
//                map.put("taskId", taskId);
//            }
//            // 流水号
//            XjrBaseTempfield tempKeyvalue = xjrBaseTempfieldService.getByIdAndType(processInstanceId, "19");
//            if (tempKeyvalue != null) {
//                String colValue = tempKeyvalue.getFvalue();
//                map.put("serialNumber", colValue);
//            }
//            // 流程实例ID
//            map.put("processInstanceId", processInstanceId);
//            // 流程状态
//            if (endActivityId != null) {
//                map.put("processStatus", "结束");
//            } else {
//                map.put("processStatus", "进行中");
//            }
//            // 任务发起人
////            XjrBaseUser xjrBaseUser = userService.getUserById(startUserId);
//            String fRealname = "";
////            if (xjrBaseUser != null) {
////                fRealname = xjrBaseUser.getRealName();
////            }
//            // 流程模板名称
//            Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
//            map.put("schemeName", deployment.getName());
//            // 任务发起人
////            map.put("startUser", fRealname);
//            // 开始时间
//            map.put("createTime", processStartTime);
//            // 总条数
////			map.put("count", count);
//            retList.add(map);
//        }
//        return retList;
//    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[xjrNwfSchemeinfo, processInstanceId, type, fvalue]
     * @return:java.lang.String
     * @Description:根据字段获取流程相关信息
     */
    private static String getProcessInfo(XjrNwfSchemeinfo xjrNwfSchemeinfo, String processInstanceId, String
            type, String value, String name) {
        String content = "";
        // 获取流程实例
        HistoricProcessInstance processInstance = null;
        if (StringUtil.isNotBlank(processInstanceId)) {
            processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        }
        // 模板信息
        if (StringUtils.equalsIgnoreCase(type, "nwfSchemeInfo")) {
            // 模板编号
            if (StringUtils.equalsIgnoreCase(value, FlowEngineConstant.nwfScheme_id)) {
                content = xjrNwfSchemeinfo.getCode();
            } else if (StringUtils.equalsIgnoreCase(value, FlowEngineConstant.nwfScheme_name)) {
                // 模板名称
                content = xjrNwfSchemeinfo.getName();
            } else if (StringUtils.equalsIgnoreCase(value, FlowEngineConstant.nwfScheme_category)) {
                // 模板分类
                XjrBaseDataItemDetail baseDataItemDetail = dataItemDetailService.getById(xjrNwfSchemeinfo.getCategory());
                if (baseDataItemDetail != null) {
                    content = baseDataItemDetail.getItemName();
                }
            } else if (StringUtils.equalsIgnoreCase(value, FlowEngineConstant.processInstanceId)) {
                content = processInstanceId;
            } else {
                // 模板备注
                content = xjrNwfSchemeinfo.getDescription();
            }
        } else if (StringUtils.equalsIgnoreCase(type, "startUserInfo")) {
            // 流程发起时间
            String startUserId = "";
            if (processInstance != null) {
                startUserId = processInstance.getStartUserId();
            } else {
                //当前登录用户
                startUserId = SecureUtil.getUserId();
            }
            // 发起人信息
            XjrBaseUser baseUser = userService.getById(startUserId);
            if (baseUser != null) {
                if (StringUtils.equalsIgnoreCase(value, FlowEngineConstant.start_user_name)) {
                    content = baseUser.getUserId();
                } else if (StringUtils.equalsIgnoreCase(value, FlowEngineConstant.start_user_id)) {
                    content = baseUser.getRealName();
                } else if (StringUtils.equalsIgnoreCase(value, FlowEngineConstant.start_user_company)) {
                    String companyId = baseUser.getCompanyId();
                    XjrBaseCompany company = companyService.getById(companyId);
                    content = company != null ? company.getFullName() : "";
                } else if (StringUtils.equalsIgnoreCase(value, FlowEngineConstant.start_user_depart)) {
                    List<XjrBaseUserRelation> userRelations = userRelationService.getObjectsOfUser(startUserId, 3);
                    for (int i = 0; i < userRelations.size(); i++) {
                        XjrBaseUserRelation xjrBaseUserRelation = userRelations.get(i);
                        XjrBaseDepartment xjrBaseDepartment = departmentService.getById(xjrBaseUserRelation.getObjectId());
                        content = xjrBaseDepartment != null ? xjrBaseDepartment.getFullName() : "";
                        if (StringUtil.isNotBlank(content)) {
                            break;
                        }
                    }
                }
            }
        } else if (StringUtils.equalsIgnoreCase(type, "startDateInfo")) {
            Date startTime = null;
            if (processInstance != null) {
                startTime = processInstance.getStartTime();
            } else {
                startTime = new Date();
            }
            // 流程发起时间
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(value);
            content = simpleDateFormat.format(startTime);
        } else if (StringUtils.equalsIgnoreCase(type, "randomNum")) {
            // 随机数
            if (StringUtils.equalsIgnoreCase(value, "1")) {
                // 两位随机数
                content = StringUtil.random(2);
            } else if (StringUtils.equalsIgnoreCase(value, "2")) {
                // 4位随机数
                content = StringUtil.random(4);
            } else if (StringUtils.equalsIgnoreCase(value, "3")) {
                // 6六位随机数
                content = StringUtil.random(6);
            } else if (StringUtils.equalsIgnoreCase(value, "4")) {
                XjrBaseTempfield byIdAndType = xjrBaseTempfieldService.getByIdAndType(processInstanceId, "19");
                if (byIdAndType != null) {
                    content = byIdAndType.getFvalue();
                }

            }
        } else if (StringUtils.equalsIgnoreCase(type, "operation")) {
            // operation
            if (StringUtils.equalsIgnoreCase(value, "2")) {
                // "+"号
                content = "+";
            } else {
                // "-"号
                content = "-";
            }
        } else if (StringUtils.equalsIgnoreCase(type, "FormTitle")) {
            // 标题
            content = value;
        } else if (StringUtils.equalsIgnoreCase(type, "FormId") || StringUtil.equalsIgnoreCase(type, "condition") || StringUtil.equalsIgnoreCase("parameter", type)) {
            // 表单字段
            if (processInstance != null) {
                HistoricVariableInstance variableName = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(value).singleResult();
                if (variableName != null) {
                    String variable = String.valueOf(variableName.getValue());
                    content = variable;
                }
            }
        } else if (StringUtils.equalsIgnoreCase(type, "customInfo")) {
            content = name;
        }
        return content;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[deploymentId, processInstanceId]
     * @return:java.lang.String
     * @Description:流程任务命名规则
     */
    public static String taskNameRule(String processDefinitionId, String processInstanceId) {
        StringBuilder taskName = new StringBuilder();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        if (processDefinition != null) {
            // Description存放的是流程信息模板ID
            String nwfSchemeInfoId = processDefinition.getDescription();
            // 流程模板里的配置信息
            XjrNwfScheme nwfScheme = nwfSchemeService.getBySchemeInfoId(nwfSchemeInfoId);
            XjrNwfSchemeinfo nwfSchemeinfo = nwfSchemeInfoService.getById(nwfSchemeInfoId);
            if (nwfScheme != null) {
                String json = nwfScheme.getFjson();
                JSONArray ruleArray = JSONObject.parseObject(json).getJSONObject("properties").getJSONArray("ruleName");
                if (!Collections.isEmpty(ruleArray)) {
                    for (int i = 0; i < ruleArray.size(); i++) {
                        JSONObject ruleMap = ruleArray.getJSONObject(i);
                        String content = "";
                        String name = ruleMap.getString("name");
                        String type = ruleMap.getString("type");
                        String value = ruleMap.getString("id");
                        content = getProcessInfo(nwfSchemeinfo, processInstanceId, type, value, name);
                        taskName.append(content);
                    }
                } else {
                    taskName = new StringBuilder(nwfSchemeinfo.getName());
                }
                try {
                    runtimeService.setProcessInstanceName(processInstanceId, taskName.toString());
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
        return taskName.toString();
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[taskId, currentUser, paramMap, userJson]
     * @return:java.util.Map<java.lang.String,java.lang.Object>
     * @Description:完成任务
     */
    public static Map<String, Object> completeTask(String currentuserId, JSONObject paramMap) throws Exception {
        JSONObject result = new JSONObject();
        JSONObject retObj = new JSONObject();
        String taskId = paramMap.getString("taskId");
        // 数据id主键
        JSONArray keyValue = paramMap.getJSONArray("keyValue");
        // 获取按钮的值
       String btnValue = paramMap.getString("btnValue");
        // 任务的审批意见
        String message = paramMap.getString("message");
        // 签章ID
        String esignature = paramMap.getString("esignature");
        // 签章密码
        String esignaturePwd = paramMap.getString("esignature_pwd");
        // 传阅人列表
        JSONArray forwarders = paramMap.getJSONArray("forwarderList");
        // 目标节点
        String targetActivitiId = paramMap.getString("rejectNodeId");
        // 根据任务id查找数据id
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            throw new Exception("任务不存在或者已审批!!!!");
        }
        String processInstanceId = task.getProcessInstanceId();
        //保存当前任务的相关信息
        XjrBaseTempfield tempfield = new XjrBaseTempfield();
        tempfield.setFkey(processInstanceId + StringPool.UNDERSCORE + task.getTaskDefinitionKey());
        tempfield.setFvalue(JSON.toJSONString(paramMap));
        tempfield.setType("32");
        xjrBaseTempfieldService.save(tempfield);
        //判断是否放入回收站
        XjrBaseTempfield byIdAndType = xjrBaseTempfieldService.getByIdAndType(processInstanceId, "18");
        if (byIdAndType != null) {
            throw new Exception("流程已被放入回收站,不可审批此任务!!!");
        }
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        // 业务ID
        String businessKey = processInstance.getBusinessKey();
        // 部署id
        String deploymentId = processInstance.getDeploymentId();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
        String version = String.valueOf(processDefinition.getVersion());
        String nwfSchemeInfoId = getNwfSchemeInfoIdByDepId(deploymentId);
        XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(nwfSchemeInfoId);
        XjrNwfScheme xjrNwfScheme = nwfSchemeService.getBySchemeInfoId(nwfSchemeInfoId);
        String json = xjrNwfScheme.getFjson();
        // 验证签章密码是否正确
        String nodeInfo = FlowableUtil.getNodeInfo(processInstanceId, null, "5");
        if (StringUtils.isNotBlank(nodeInfo)) {
            String needpassWord = JSON.parseObject(nodeInfo).getString("needpassword");
            if (StringUtils.equals(needpassWord, "2")) {
                boolean isRight = bseStampService.validatePwd(esignature, esignaturePwd);
                if (!isRight) {
                    retObj.put("retCode", 1);
                    return retObj;
                }
            }
        }
        // 将审批意见相关数据放到map中存储
        JSONObject messageMap = new JSONObject();
        messageMap.put("message", message);

        messageMap.put("btnValue", btnValue);
        messageMap.put("esignature", esignature);
        message = JSONObject.toJSONString(messageMap);
        // 提交审批意见
        Comment comment = taskService.addComment(taskId, processInstanceId, message);
        //修改审批意见的处理人
        comment.setUserId(currentuserId);
        taskService.saveComment(comment);
        // 获取表单数据
        JSONObject formValues = new JSONObject();
        if (CollectionUtil.isNotEmpty(keyValue)) {
            formValues = getFormData(JSONArray.toJSONString(keyValue), taskId, nwfSchemeInfoId, deploymentId);
        }
        // 追加传阅人
        if (CollectionUtil.isNotEmpty(forwarders)) {
            String forwarderListStr = JSON.toJSONString(forwarders);
            XjrBaseTempfield newXjrTempKeyValue = new XjrBaseTempfield();
            newXjrTempKeyValue.setFkey(processInstanceId + "_" + task.getTaskDefinitionKey());
            newXjrTempKeyValue.setFvalue(forwarderListStr);
            newXjrTempKeyValue.setType("7");
            xjrBaseTempfieldService.save(newXjrTempKeyValue);
            createSubTask(taskId, task.getFormKey(), forwarderListStr);
        }
        // 按钮的值
        formValues.put(task.getTaskDefinitionKey() + StringPool.UNDERSCORE + "btnValue", btnValue);
        Map<String, Object> variables = setParamVariable(taskId, processDefinition.getId(), xjrNwfScheme, formValues, processInstanceId);
        if (FlowEngineConstant.REJECT.equals(btnValue)) {
            taskService.claim(taskId, currentuserId);
            nwfTaskMapper.setEndTime(taskId, LocalDateTime.now());
            rollBack(processInstanceId, targetActivitiId);
            return retObj;
        } else if (FlowEngineConstant.FINISH.equals(btnValue)) {
            // 执行结束方法
            taskService.claim(taskId, currentuserId);
            nwfTaskMapper.setEndTime(taskId, LocalDateTime.now());
            suspendProcessInstance(processInstanceId, "流程被结束", 0);
            return retObj;
        }
        // 判断任务类型
        DelegationState delegationState = task.getDelegationState();
        // 判断是否是委托任务
        if (delegationState != null && StringUtils.equalsIgnoreCase(delegationState.name(), "PENDING")) {
            // 被委派人处理完成任务
            taskService.resolveTask(taskId);
        }
        // 设置当前操作人，对于调用活动可以获取到当前操作人
        List<FlowElement> node = getCallActivityNode(task.getTaskDefinitionKey(), processInstance.getProcessDefinitionId(), 1, new ArrayList<String>());
        if (CollectionUtil.isNotEmpty(node)) {
            for (FlowElement flowElement : node) {
                if (flowElement instanceof Activity) {
                    String activityId = flowElement.getId();
                    XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(nwfSchemeInfoId + StringPool.UNDERSCORE + activityId + StringPool.UNDERSCORE + version, "39");
                    if (xjrBaseTempfield != null) {
                        String properties = xjrBaseTempfield.getFvalue();
                        JSONObject propertiesObj = JSONObject.parseObject(properties);
                        Boolean callType = propertiesObj.getBoolean("callType");
                        if (!callType) {
                            //多实例
                            JSONArray callStartUser = getCallStartUser(propertiesObj, processInstanceId, nwfSchemeInfoId, formValues);
                            if (CollectionUtil.isEmpty(callStartUser)) {
                                throw new Exception(flowElement.getName() + "节点发起人集合为空!");
                            }
                            variables.put(activityId + StringPool.UNDERSCORE + "usernamelist", callStartUser);
                            variables.put(activityId + StringPool.UNDERSCORE + "count", callStartUser.size());
                        } else {
                            //单实例
                            String subProcessInitiator = propertiesObj.getString("subProcessInitiator");
                            List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityId(subProcessInitiator).list();
                            String assignee = "";
                            if (CollectionUtil.isNotEmpty(list)) {
                                HistoricActivityInstance historicActivityInstance = list.get(0);
                                assignee = historicActivityInstance.getAssignee();
                                if (StringUtil.equals(historicActivityInstance.getActivityType(), "startEvent")) {
                                    assignee = processInstance.getStartUserId();
                                }
                            }
                            if (StringUtil.isBlank(assignee)) {
                                assignee = currentuserId;
                            }
                            // 设置流程发起人
                            identityService.setAuthenticatedUserId(assignee);
                            break;
                        }
                    }
                }
            }
        }
        // 签收任务
        taskService.claim(taskId, currentuserId);
        taskService.setAssignee(taskId, currentuserId);
        // 提交任务
        //更新表单信息businessKey
        JSONArray businessKeyObject = new JSONArray();
        if (StringUtil.isNotBlank(businessKey)) {
            businessKeyObject = JSONArray.parseArray(businessKey);
        }
        if (CollectionUtil.isNotEmpty(keyValue)) {
            businessKeyObject.addAll(keyValue);
        }
        ObjectMapper mapper = new ObjectMapper();
        JSONArray newBusinessKey = JSONArray.parseArray(JSON.toJSONString(mapper.readValue(businessKeyObject.toJSONString(), HashSet.class)));
        runtimeService.updateBusinessKey(processInstanceId, newBusinessKey.toJSONString());
        // 会签节点的候选人
        String resourceId = task.getTaskDefinitionKey();
        String key = nwfSchemeInfoId + StringPool.UNDERSCORE + resourceId + StringPool.UNDERSCORE + version;
        Integer fHandle = JSONObject.parseObject(xjrNwfScheme.getFjson()).getJSONObject("properties").getInteger("F_Handle");
        //如果是会签
//        String fjson = xjrNwfScheme.getFjson();
//        JSONArray childShapes = (JSONObject.parseObject(fjson)).getJSONArray("childShapes");
//        JSONArray nextMultiinstanceResourceId = JsonUtil.getNextMultiinstanceResourceId(childShapes, resourceId);
//        for (int i = 0; i < nextMultiinstanceResourceId.size(); i++) {
//            String mulResourceId = nextMultiinstanceResourceId.getString(i);
//            JSONArray userArrays = new JSONArray();
//            userArrays.add("xxx");
//            variables.put(mulResourceId + StringPool.UNDERSCORE + "usernamelist", userArrays);
//        }
        taskService.setVariables(taskId, formValues);
        variables.put("btnValue", btnValue);
        try {
            taskService.complete(taskId, variables);
        } catch (Exception e) {
            if (StringUtil.startsWithIgnoreCase(e.getMessage(), "No outgoing sequence flow")) {
                throw new Exception("当前审批不满足任一流转条件，请修改数据或联系管理员");
            } else {
                log.error("流程流转发生错误，错误原因:" + e.getMessage());
                throw new Exception("流程流转发生错误，具体错误请在控制台或日志中查看");
            }
         }
        //获取按钮信息
        XjrBaseTempfield btnInfo = xjrBaseTempfieldService.getByIdAndType(key, "2");
        if (btnInfo != null) {
            JSONArray btnInfoArray = JSONArray.parseArray(btnInfo.getFvalue());
            for (int i = 0; i < btnInfoArray.size(); i++) {
                JSONObject btnObject = btnInfoArray.getJSONObject(i);
                if (btnValue.equals(btnObject.getString("val")) && btnObject.getBoolean("check")) {
                    //是否为脚本任务
                    JSONObject info = btnObject.getJSONObject("info");
                    String type = btnObject.getString("type");
                    if (info != null) {
                        //处理脚本任务
                        scriptHandler(processInstanceId, nwfSchemeInfoId, info, type);
                    }
                }
            }
        }
        //保存选中的按钮值变量
        XjrBaseTempfield xjrBaseTempfield = new XjrBaseTempfield();
        xjrBaseTempfield.setType("23");
        xjrBaseTempfield.setFvalue(btnValue);
        xjrBaseTempfield.setFkey(processInstanceId + StringPool.UNDERSCORE + resourceId + StringPool.UNDERSCORE + SecureUtil.getUserId());
        xjrBaseTempfieldService.save(xjrBaseTempfield);
        result.putAll(pretreatmentTask(processInstanceId, deploymentId, resourceId));
        return result;
    }


    public static JSONArray getCallStartUser(JSONObject propertiesObj, String processInstanceId, String xjrNwfSchemeinfoId, Map<String, Object> formValues) throws Exception {
        HistoricProcessInstance processInstance = null;
        if (StringUtil.isNotBlank(processInstanceId)) {
            processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        }
        XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(xjrNwfSchemeinfoId);
        String optionType = propertiesObj.getString("optionType");

        JSONArray userArrays = new JSONArray();
        if (StringUtil.equals(optionType, "user")) {
            JSONArray initiatorConfiguration = propertiesObj.getJSONArray("initiatorConfiguration");
            for (int i = 0; i < initiatorConfiguration.size(); i++) {
                JSONObject jsonObject = initiatorConfiguration.getJSONObject(i);
                String f_userId = jsonObject.getString("F_UserId");
                userArrays.add(f_userId);
            }
        } else if (StringUtil.equals(optionType, "formData")) {
            //表单数据
            JSONObject initiatorConfiguration = propertiesObj.getJSONObject("initiatorConfiguration");
            String resourceId = initiatorConfiguration.getString("resourceId");
            String bindTable = initiatorConfiguration.getString("bindTable");
            String fieldId = initiatorConfiguration.getString("fieldId");
            String type = initiatorConfiguration.getString("type");
            if(StringUtil.equals(type, "hideComponents")){
                String value = gethideComponentsValue(initiatorConfiguration);
                if (value != null) {
                    String[] split = String.valueOf(value).split(StringPool.COMMA);
                    for (String s : split) {
                        userArrays.add(s);
                    }
                }
            } else {
                String key = resourceId + StringPool.UNDERSCORE + bindTable + StringPool.UNDERSCORE + fieldId;
                Object value = null;
                if (StringUtil.isNotBlank(processInstanceId)) {
                    value = runtimeService.getVariable(processInstanceId, key);
                }
                if (StringUtil.isBlank(processInstanceId) || value == null) {
                    value = formValues.get(key);
                }
                if (value != null) {
                    String[] split = String.valueOf(value).split(StringPool.COMMA);
                    for (String s : split) {
                        userArrays.add(s);
                    }
                }
            }
        } else if (StringUtil.equals(optionType, "API")) {
            //参数
            JSONObject initiatorConfiguration = propertiesObj.getJSONObject("initiatorConfiguration");
            JSONArray params = initiatorConfiguration.getJSONArray("params");
            //返回的字段
            String field = initiatorConfiguration.getString("field");
            String interfaceId = initiatorConfiguration.getString("interfaceId");
            Map<String, String> apiParamMap = new HashMap<>();
            HttpServletRequest request = WebUtil.getRequest();
            for (int j = 0; j < params.size(); j++) {
                JSONObject param = params.getJSONObject(j);
                String paramValue = param.getString("paramValue");
                String paramName = param.getString("paramName");
                //参数值的类型
                Integer paramValType = param.getInteger("paramValType");
                String startUserId = null;
                if (processInstance != null) {
                    startUserId = processInstance.getStartUserId();
                } else {
                    startUserId = SecureUtil.getUserId();
                }
                XjrBaseUser user = userService.getById(startUserId);
                if (paramValType == 1) {
                    //变量
                    if (StringUtil.equals(paramValue, FlowEngineConstant.start_user_id)) {
                        paramValue = user.getUserId();
                    } else if (StringUtil.equals(paramValue, FlowEngineConstant.start_user_name)) {
                        //发起人名字
                        paramValue = user.getRealName();
                    } else if (StringUtil.equals(paramValue, FlowEngineConstant.start_user_company)) {
                        //发起人公司id
                        paramValue = user.getCompanyId();
                    } else if (StringUtil.equals(paramValue, FlowEngineConstant.start_user_depart)) {
                        //发起人部门id
                        List<XjrBaseUserRelation> objectsOfUser = userRelationService.getObjectsOfUser(startUserId, 3);
                        if (CollectionUtil.isNotEmpty(objectsOfUser)) {
                            XjrBaseUserRelation xjrBaseUserRelation = objectsOfUser.get(0);
                            paramValue = xjrBaseUserRelation.getObjectId();
                        }
                    } else if (StringUtils.equalsIgnoreCase(paramValue, FlowEngineConstant.nwfScheme_id)) {
                        paramValue = xjrNwfSchemeinfo.getCode();
                    } else if (StringUtils.equalsIgnoreCase(paramValue, FlowEngineConstant.nwfScheme_name)) {
                        // 模板名称
                        paramValue = xjrNwfSchemeinfo.getName();
                    } else if (StringUtils.equalsIgnoreCase(paramValue, FlowEngineConstant.nwfScheme_category)) {
                        // 模板分类
                        XjrBaseDataItemDetail baseDataItemDetail = dataItemDetailService.getById(xjrNwfSchemeinfo.getCategory());
                        if (baseDataItemDetail != null) {
                            paramValue = baseDataItemDetail.getItemName();
                        }
                    } else if (StringUtils.equalsIgnoreCase(paramValue, FlowEngineConstant.processInstanceId)) {
                        paramValue = processInstanceId;
                    } else if (StringUtils.equalsIgnoreCase(paramValue, FlowEngineConstant.nwfScheme_description)) {
                        // 模板备注
                        paramValue = xjrNwfSchemeinfo.getDescription();
                    } else if (FlowEngineConstant.time_pattern.contains(paramValue)) {
                        //发起时间
                        Date startTime = null;
                        if (processInstance != null) {
                            startTime = processInstance.getStartTime();
                        } else {
                            startTime = new Date();
                        }
                        // 流程发起时间
                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(paramValue);
                        paramValue = simpleDateFormat.format(startTime);
                    } else {
                        Object value = null;
                        if (StringUtil.isNotBlank(processInstanceId)) {
                            value = runtimeService.getVariable(processInstanceId, paramValue);
                        } else {
                            value = formValues.get(paramValue);
                        }
                        if (value != null) {
                            paramValue = String.valueOf(value);
                        }
                    }
                }
                apiParamMap.put(paramName, paramValue);
            }
            MediaType JSONType = MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE);
            okhttp3.RequestBody body = okhttp3.RequestBody.create(JSONType, JSON.toJSONString(apiParamMap));
            String host = serverConfig.getLocalUrl();
            String address = host + StringPool.SLASH + "xjr-interface-info" + StringPool.SLASH + "execute" + StringPool.SLASH + interfaceId;
            OkHttpClient client = new OkHttpClient();
            HttpUrl parse = HttpUrl.parse(address);
            HttpUrl.Builder builder = Objects.requireNonNull(parse).newBuilder();
            Request.Builder url = new Request.Builder().url(builder.build());
            url.addHeader("isWorkFlow", "true");
            url.addHeader("Authorization", request.getHeader("Authorization"));
            Request req = url.post(body).build();
            okhttp3.Response response = client.newCall(req).execute();
            if (response.isSuccessful()) {
                String responseBody = Objects.requireNonNull(response.body()).string();
                JSONObject responseBodyObj = JSONObject.parseObject(responseBody);
                if (responseBodyObj.getBoolean("success")) {
                    JSONObject data = responseBodyObj.getJSONObject("data");
                    if (CollectionUtil.isNotEmpty(data)) {
                        Object o = data.get(field);
                        if (o != null) {
                            String value = String.valueOf(o);
                            if (StringUtil.isNotBlank(value)) {
                                String[] split = value.split(StringPool.COMMA);
                                for (String s : split) {
                                    userArrays.add(s);
                                }
                            }
                        }
                    }
                }
            }
        } else if (StringUtil.equals(optionType, "SQL")) {
            JSONObject initiatorConfiguration = propertiesObj.getJSONObject("initiatorConfiguration");
            JSONArray templateData = initiatorConfiguration.getJSONArray("templateData");
            String fDataSourceId = initiatorConfiguration.getString("F_ObjId");
            String sql = "";
            // 添加参数
            for (int j = 0; j < templateData.size(); j++) {
                JSONObject object = templateData.getJSONObject(j);
                String beforeText = object.getString("beforeText");
                if (StringUtil.isNotBlank(beforeText)) {
                    sql = sql + object.getString("beforeText");
                }
                String infoValue = object.getString("id");
                String infoType = object.getString("type");
                String resourceId = object.getString("resourceId");
                String bindTable = object.getString("bindTable");
                String param = object.getString("value");
                if (StringUtil.equalsIgnoreCase(infoType, "condition")) {
                    if (infoValue != null && (!StringUtil.equals("", infoValue))) {
                        infoValue = resourceId + StringPool.UNDERSCORE + bindTable + StringPool.UNDERSCORE + infoValue;
                    }
                }
                if (StringUtil.equalsIgnoreCase(infoType, "hideComponents")) {
                    param = gethideComponentsValue(object);
                } else if (StringUtil.equals(infoType, "parameter") && StringUtil.isBlank(processInstanceId)) {
                    param = String.valueOf(formValues.get(param));
                } else if (infoType != null) {
                    param = getProcessInfo(xjrNwfSchemeinfo, processInstanceId, infoType, infoValue, null);
                }
                if (StringUtil.isNotBlank(param)) {
                    sql = sql + param;
                }
                String afterText = object.getString("afterText");
                if (StringUtil.isNotBlank(afterText)) {
                    sql = sql + afterText;
                }
            }
//            sql = StringUtil.replace(sql, StringPool.NEWLINE, StringPool.EMPTY);
            String field = initiatorConfiguration.getString("field");
            List<Entity> sqlResult = dbExecutor.executeQuery(fDataSourceId, sql);
            if (sqlResult.size() > 0) {
                for (Entity entity : sqlResult) {
                    Object o = entity.get(field);
                    if (o != null) {
                        String value = String.valueOf(o);
                        if (StringUtil.isNotBlank(value)) {
                            userArrays.add(value);
                        }
                    }
                }
            }
        }
        return userArrays;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[processId]
     * @return:void
     * @Description:挂起流程
     */
    public static void suspendProcessInstance(String processId, String message, Integer isSuspend) {
        log.info("【挂起流程】实例ID：" + processId);
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
        if (processInstance != null) {
            boolean suspended = processInstance.isSuspended();
            if (!suspended) {
                runtimeService.suspendProcessInstanceById(processId);
            }
            XjrBaseTempfield xjrBaseTempfield = null;
            //添加挂起原因
            if (isSuspend == 1) {
                //挂起操作
                xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(processId, "36");
                //添加挂起信息
                JSONObject jsonObject = new JSONObject();
                String userId = SecureUtil.getUserId();
                XjrBaseUser xjrBaseUser = userService.getById(userId);
                jsonObject.put("candidate", StringUtil.isNotBlank(xjrBaseUser.getRealName()) ? xjrBaseUser.getRealName() : xjrBaseUser.getAccount());
                jsonObject.put("candidateUserId", userId);
                jsonObject.put("activityType", "suspend");
                jsonObject.put("startTime", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                jsonObject.put("endTime", cn.hutool.core.date.DateUtil.now());
                jsonObject.put("time", cn.hutool.core.date.DateUtil.now());
                XjrBaseTempfield xjrBaseTempfield1 = new XjrBaseTempfield();
                xjrBaseTempfield1.setType("41");
                xjrBaseTempfield1.setFvalue(jsonObject.toJSONString());
                xjrBaseTempfield1.setFkey(processId);
                xjrBaseTempfield1.setCreateTime(new Date());
                xjrBaseTempfieldService.save(xjrBaseTempfield1);
            } else {
                xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(processId, "33");
            }
            if (xjrBaseTempfield != null) {
                xjrBaseTempfield.setFvalue(message);
                xjrBaseTempfieldService.updateById(xjrBaseTempfield);
            } else {
                xjrBaseTempfield = new XjrBaseTempfield();
                xjrBaseTempfield.setFkey(processId);
                xjrBaseTempfield.setFvalue(message);
                if (isSuspend == 1) {
                    xjrBaseTempfield.setType("36");
                } else {
                    xjrBaseTempfield.setType("33");
                }
                xjrBaseTempfieldService.save(xjrBaseTempfield);
            }
        }
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[nwfSchemeInfoId, taskId, currentUserId]
     * @return:void
     * @Description:自动同意规则
     */
    public static Map<String, Object> automaticTask(String json, String taskId, String nwfSchemeInfoId, String
            deployId) throws Exception {
        // 先判断任务是否已结束
        //是否为会签
        boolean multiInstance = isMultiInstance(taskId);
        Set<String> userList = new HashSet<>();
        Map<String, Object> result = new HashMap<>();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            return result;
        }
        List<HistoricActivityInstance> histList = historyService.createHistoricActivityInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricActivityInstanceStartTime().asc().list();
        if (task != null) {
            String processInstanceId = task.getProcessInstanceId();
            HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            // 流程发起人
            String startUserId = processInstance.getStartUserId();
            if (multiInstance) {
                userList.add(task.getAssignee());
            } else {
                // 获取任务的候选人
                String version = getVersionByDepId(deployId);
                String key = nwfSchemeInfoId + StringPool.UNDERSCORE + task.getTaskDefinitionKey() + StringPool.UNDERSCORE + version;
                // 查询keyvalue表
                XjrBaseTempfield baseTempfield = xjrBaseTempfieldService.getByIdAndType(key, "4");
                JSONArray userArray = new JSONArray();
                if (baseTempfield != null) {
                    userArray = JSONObject.parseArray(baseTempfield.getFvalue());
                }
                userList = checkUsers(task.getId(), histList, userArray);
            }
            // 查询模板信息配置看是否有配置自动同意规则
            if (StringUtils.isNotBlank(json)) {
                JSONObject properties = JSON.parseObject(json).getJSONObject("properties");
                String fAgree = properties.getString("F_Agree");
                if (StringUtils.isNotBlank(fAgree)) {
                    XjrBaseUser startUser = userService.getById(startUserId);
                    result = checkAutoType(taskId, processInstanceId, startUser.getUserId(), userList, fAgree);
                }
            }
        } else {
            log.info("任务已经结束!");
        }
        return result;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[processInstanceId, currentUserId, userJson]
     * @return:java.util.Map<java.lang.String,java.lang.Object>
     * @Description:候选人处理器，判断是否有候选条件和无对应人处理
     */
    public static JSONObject candidateHandler(String configJson, Set<String> processInstanceIds) throws
            Exception {
        List<XjrBaseUser> xjrBaseUserList = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.USER_LIST_CACHE_KEY);
        JSONArray retArray = new JSONArray();
        JSONObject retObj = new JSONObject();
        // 会签任务会有多个任务共用同一个实例ID
        for (String processInstanceId : processInstanceIds) {
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            String deployId = historicProcessInstance.getDeploymentId();
            String version = getVersionByDepId(deployId);
            // 流程模板信息ID
            String nwfSchemeInfoId = getNwfSchemeInfoIdByDepId(deployId);
            XjrNwfScheme xjrNwfScheme = nwfSchemeService.getBySchemeInfoId(nwfSchemeInfoId);
            //查看模板是否是选择下一节点审批人
            Boolean f_assign = JSONObject.parseObject(xjrNwfScheme.getFjson()).getJSONObject("properties").getBoolean("F_Assign");
            List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
            for (Task task : taskList) {
                ArrayList<String> candidates = nwfTaskMapper.getUserIdByTask(task.getId());
                if (CollectionUtil.isNotEmpty(candidates)) {
                    for (String candidate : candidates) {
                        taskService.deleteCandidateUser(task.getId(), candidate);
                    }
                }
                List<HistoricActivityInstance> histList = historyService.createHistoricActivityInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricActivityInstanceStartTime().asc().list();
                // 获取当前节点的resourceId
                String currentResourceId = task.getTaskDefinitionKey();
                String key = nwfSchemeInfoId + StringPool.UNDERSCORE + currentResourceId + StringPool.UNDERSCORE + version;
                // 查询keyvalue表
                XjrBaseTempfield baseTempfield = xjrBaseTempfieldService.getByIdAndType(key, "4");
                JSONArray userArray = new JSONArray();
                if (baseTempfield != null) {
                    userArray = JSONObject.parseArray(baseTempfield.getFvalue());
                }
                Set<String> assigns = checkUsers(task.getId(), histList, userArray);
                if (!isMultiInstance(task.getId())) {
                    if (f_assign) {
                        //上一节点指定审批人
                        JSONArray assignArray = new JSONArray();
                        JSONObject jsonObject = new JSONObject();
                        //获取所有审批审批人并返回
                        if (CollectionUtil.isEmpty(assigns)) {
                            // 无对应处理人
                            jsonObject = noAssigneeHandler(configJson, task);
                            if (!jsonObject.isEmpty()) {
                                retArray.add(jsonObject);
                            }
                        } else {
                            for (String assign : assigns) {
                                Optional<XjrBaseUser> userOption = xjrBaseUserList.stream().filter(s -> s.getUserId().equals(assign)).findFirst();
                                if (userOption.isPresent()) {
                                    XjrBaseUser xjrBaseUser = userOption.get();
                                    JSONObject userInfoJson = new JSONObject();
                                    userInfoJson.put("F_UserId", xjrBaseUser.getUserId());
                                    userInfoJson.put("F_RealName", xjrBaseUser.getRealName());
                                    userInfoJson.put("F_Account", xjrBaseUser.getAccount());
                                    userInfoJson.put("F_Gender", xjrBaseUser.getGender());
                                    userInfoJson.put("checked", true);
                                    assignArray.add(userInfoJson);
                                }
                            }
                            jsonObject.put("userList", assignArray);
                            jsonObject.put("taskId", task.getId());
                            jsonObject.put("name", task.getName());
                            retArray.add(jsonObject);
                        }
                    } else {
                        if (CollectionUtil.isEmpty(assigns)) {
                            // 无对应处理人
                            JSONObject jsonObject = noAssigneeHandler(configJson, task);
                            if (CollectionUtil.isNotEmpty(jsonObject)) {
                                retArray.add(jsonObject);
                            }
                        } else {
                            //添加动态候选人
                            for (String userId : assigns) {
                                taskService.addCandidateUser(task.getId(), userId);
                            }
                        }
                    }
                } else if (StringUtil.equals(task.getAssignee(), "xxx")) {
                    Integer fHandle = JSONObject.parseObject(xjrNwfScheme.getFjson()).getJSONObject("properties").getInteger("F_Handle");
                    JSONArray userArrays = new JSONArray();
                    //如果是会签
                    XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(nwfSchemeInfoId + StringPool.UNDERSCORE + task.getTaskDefinitionKey() + StringPool.UNDERSCORE + version, "1");
                    if (xjrBaseTempfield != null) {
                        String fvalue = xjrBaseTempfield.getFvalue();
                        if (StringUtil.isNotBlank(fvalue)) {
                            Set<String> userSet = FlowableUtil.checkUsers(task.getProcessInstanceId(), histList, JSONObject.parseObject(fvalue).getJSONArray("users"));
                            userArrays = new JSONArray(new ArrayList<>(userSet));
                            if (CollectionUtil.isEmpty(userArrays)) {
                                // 获取无对应处理人的配置
                                if (fHandle != null && fHandle == 1) {
                                    // 添加超级管理员下的人员为候选人
                                    XjrBaseRole sysRole = roleService.getSysRole();
                                    List<XjrBaseUser> usersOfObject = userRelationService.getUsersOfObject(sysRole.getRoleId(), 1);
                                    for (XjrBaseUser xjrBaseUser : usersOfObject) {
                                        userArrays.add(xjrBaseUser.getUserId());
                                    }
                                }
                            }
                        }
                    }
                    taskService.setVariable(task.getId(), task.getTaskDefinitionKey() + StringPool.UNDERSCORE + "usernamelist", userArrays);
                    taskService.setVariable(task.getId(), task.getTaskDefinitionKey() + StringPool.UNDERSCORE + "count", userArrays.size());
                    // 减签
                    runtimeService.deleteMultiInstanceExecution(task.getExecutionId(), false);
                    for (int i = 0; i < userArrays.size(); i++) {
                        JSONObject map = new JSONObject();
                        map.put("username", userArrays.getString(i));
                        runtimeService.addMultiInstanceExecution(task.getTaskDefinitionKey(), task.getProcessInstanceId(), map);
                    }
                }
            }
        }
        retObj.put("retCode", CollectionUtil.isEmpty(retArray) ? 0 : 2);
        retObj.put("CandidateInfo", retArray);
//        retObj.putAll(automaticTask(configJson, !Collections.isEmpty(taskList) ? taskList.get(0).getId() : "", currentUserId));
        return retObj;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[processInstanceId, startUser, userList, fAgree, currentUser]
     * @return:void
     * @Description:确认自动同意类型, 1.候选审批人包含流程任务发起人 2.候选审批人包含上一节点审批人  3.候选审批人再此流程中审批过
     */
    private static Map<String, Object> checkAutoType(String taskId, String processInstanceId, String
            startUserId, Set<String> userList, String fAgree) throws Exception {
        boolean flag = false;
        String currentUserId = "";
        Map<String, Object> result = new HashMap<>();
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().taskId(taskId).processInstanceId(processInstanceId).list();
        List<HistoricActivityInstance> histList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityType("userTask").finished().orderByHistoricActivityInstanceStartTime().asc().list();
        Set<String> activitiIds = new HashSet<>();
        if (CollectionUtil.isNotEmpty(historicTaskInstanceList)) {
            HistoricTaskInstance historicTaskInstance = historicTaskInstanceList.get(0);
            if (historicTaskInstance != null) {
                // 上一任务节点
                List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityId(historicTaskInstance.getTaskDefinitionKey()).list();
                if (CollectionUtil.isNotEmpty(historicActivityInstances)) {
                    Set<HashMap<String, Object>> forwardTaskNode = getUsetTaskNode(historicActivityInstances.get(0).getActivityId(), processInstanceId, 2);
                    activitiIds = forwardTaskNode.stream().map(s -> s.get("activitiId").toString()).collect(Collectors.toSet());
                }
            }
        }
        // 任务候选人是同一个人
        String[] split = fAgree.split(",");
        flag:
        for (String typeStr : split) {
            if (StringUtils.equalsIgnoreCase(typeStr, "1")) {
                // 候选审批人包含流程任务发起人
                if (userList.contains(startUserId)) {
                    currentUserId = startUserId;
                    flag = true;
                    break flag;
                }
            } else if (StringUtils.equalsIgnoreCase(typeStr, "2")) {
                // 当前节点候选审批人包含上一节点审批人
                if (CollectionUtil.isNotEmpty(activitiIds)) {
                    for (String activitiId : activitiIds) {
                        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().activityId(activitiId).processInstanceId(processInstanceId).list();
                        for (HistoricActivityInstance forwardTask : list) {
                            if (forwardTask != null) {
                                if (StringUtil.equalsIgnoreCase(forwardTask.getActivityType(), "startEvent")) {
                                    if (userList.contains(startUserId)) {
                                        currentUserId = startUserId;
                                        flag = true;
                                        break flag;
                                    }
                                } else {
                                    //如果是开始节点
                                    String assignee = forwardTask.getAssignee();
                                    if (userList.contains(assignee)) {
                                        currentUserId = assignee;
                                        flag = true;
                                        break flag;
                                    }
                                }
                            }
                        }
                    }
                }
            } else {
                // 候选审批人在此流程中审批过
                // 当前任务的候选人
                Set<String> assignees = histList.stream().map(HistoricActivityInstance::getAssignee).collect(Collectors.toSet());
                for (String candidateUserId : userList) {
                    for (String assignee : assignees) {
                        if (StringUtils.equals(assignee, candidateUserId)) {
                            currentUserId = assignee;
                            flag = true;
                            break flag;
                        }
                    }
                }
            }
        }
        // 自动同意(根据上一节点的审批结果，审批内容，电子签章 进行自动同意
        if (flag) {
            // 表单数据List
            List<Map<String, Object>> formDataList = new ArrayList<>();
            JSONObject paramMap = new JSONObject();
            // 表单提交内容
            HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            String businessKey = processInstance.getBusinessKey();
            List<Map<String, Object>> businessList = (List<Map<String, Object>>) JSON.parse(businessKey);
            paramMap.put("keyValue", JSONArray.parse(businessKey));
            for (Map<String, Object> map : businessList) {
                String dataId = String.valueOf(map.get("F_Id"));
                Integer type = MapUtils.getInteger(map, "F_Type");
                Map<String, Object> customizedFormData = null;
                if (type != null && type == 2) {
                    //系统表单
                    String urlAddress = String.valueOf(map.get("F_UrlAddress"));
                    customizedFormData = getSystemFormData(dataId, urlAddress);
                } else {
                    String formId = String.valueOf(map.get("F_FormId"));
                    customizedFormData = formSchemeInfoService.getCustomFormData(formId, dataId);
                }
                Set<String> keySet = customizedFormData.keySet();
                for (String key : keySet) {
                    customizedFormData.put(key, JSONObject.toJSONString(customizedFormData.get(key)));
                }
                formDataList.add(customizedFormData);
            }
            paramMap.put("formValue", JSONObject.toJSONString(formDataList));
            paramMap.put("message", "自动同意");
            // 获取上一节点的审批意见
            List<Map<String, Object>> taskAttachments = getProcessInstanceComment(processInstanceId);
            if (!Collections.isEmpty(taskAttachments)) {
                Map<String, Object> map = taskAttachments.get(0);
                paramMap.putAll(map);
            }
            // 按钮的值
            paramMap.put("btnValue", "agree_");
            // 任务id
            paramMap.put("taskId", taskId);
            // 获取
            result = FlowableUtil.completeTask(currentUserId, paramMap);
        }
        return result;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[taskId, histList, userList, operation:0-设置任务候选人   1-不设置任务候选人]
     * @return:java.util.Set<java.lang.String>
     * @Description:筛选条件之后的候选人
     */
    public static Set<String> checkUsers(String taskId, List<HistoricActivityInstance> histList, JSONArray
            userArray) throws Exception {
        Set<String> userSet = new HashSet<>();
        if (CollectionUtil.isNotEmpty(userArray)) {
            for (int i = 0; i < userArray.size(); i++) {
                JSONObject userObject = userArray.getJSONObject(i);
                String fObjId = userObject.getString("F_ObjId");
                // 审批条件的类型
                int t = Integer.parseInt(userObject.getString("F_ObjType"));
                switch (t) {
                    case 1:
                        // 岗位,把岗位下的用户设置成候选人
                        List<XjrBaseUser> usersOfPost = userRelationService.getUsersOfObject(fObjId, 2);
                        for (XjrBaseUser xjrBaseUser : usersOfPost) {
                            userSet.add(xjrBaseUser.getUserId());
                        }
                        break;
                    case 2:
                        // 角色的限制条件
                        List<XjrBaseUser> usersOfRole = userRelationService.getUsersOfObject(fObjId, 1);
                        for (XjrBaseUser xjrBaseUser : usersOfRole) {
                            userSet.add(xjrBaseUser.getUserId());
                        }
                        break;
                    case 3:
                        // 指定用户
                        userSet.add(fObjId);
                        break;
                    case 4:
                        // 指定节点审批人(根据指定节点ID查出审批人)
                        userSet.addAll(specifyNodeLimitation(histList, fObjId));
                        break;
                    case 5:
                        // 上级领导审批,节点条件:x个节点 上y级
                        userSet.addAll(getPostLevelUsers(histList, userObject));
                        break;
                    case 6:
                        // 表单字段
                        userSet.addAll(getFormField(histList, userObject));
                        break;
                    case 7:
                        // 公司特殊岗位
                        userSet.addAll(getComOrDepSpecialUser(histList, userObject, "1"));
                        break;
                    case 8:
                        // 部门特殊岗位
                        userSet.addAll(getComOrDepSpecialUser(histList, userObject, "2"));
                        break;
                    case 9:
                        // sql指定人员
                        // 获取流程实例
                        userSet.addAll(getUserBySql(taskId, userObject));
                        break;
                    default:
                        break;
                }
            }
        }
        return userSet;
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/12/31
     * @Param:[histList, map, type]
     * @return:java.util.Set<java.lang.String>
     * @Description:
     */
    private static Set<String> getComOrDepSpecialUser(List<HistoricActivityInstance> histList, JSONObject
            userObject, String type) {
        Set<String> userSet = new HashSet<>(10);
        // 所属公司上N级的限制条件
        String level = "";
        // 特殊岗位的Id
        String specialPostId = String.valueOf(userObject.get("F_ObjId"));
        if (userObject.containsKey("limitType")) {
            level = userObject.getString("limitType");
            if (StringUtils.equals(level, "same")) {
                level = "0";
            } else if (StringUtils.equals(level, "sameS1")) {
                level = "1";
            } else if (StringUtils.equals(level, "sameS2")) {
                level = "2";
            } else if (StringUtils.equals(level, "sameS3")) {
                level = "3";
            } else if (StringUtils.equals(level, "sameMax")) {
                // 发起人所属公司最高级公司（设定99求最高级
                level = "99";
            }
        } else {
            level = "-1";
        }
        // 发起节点
        if (CollectionUtil.isNotEmpty(histList)) {
            String hisProcessInstanceId = histList.get(0).getProcessInstanceId();
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(hisProcessInstanceId).singleResult();
            Set<SpecialPostUserVo> usersOfSpecialPosts = null;
            if (historicProcessInstance != null) {
                // 获取发起人
                String startUserId = historicProcessInstance.getStartUserId();
                // 获取发起人所在公司
                XjrBaseUser xjrBaseUser = userService.getById(startUserId);
                if (xjrBaseUser != null) {
                    String fCompanyId = xjrBaseUser.getCompanyId();
                    Integer levelValue = Integer.valueOf(level);
                    // 公司特殊岗位下的用户
                    if (StringUtils.equals(type, "1")) {
                        Set<String> companyIds = new HashSet<>();
                        if (levelValue < 0) {
                            //获取所有公司
                            List<XjrBaseCompany> companyList = companyService.list();
                            if (CollectionUtil.isNotEmpty(companyList)) {
                                companyIds = companyList.stream().map(XjrBaseCompany::getCompanyId).collect(Collectors.toSet());
                            }
                        } else {
                            // 获取发起人所属公司上N级
                            companyIds.add(companyService.getCompanyIdByLevel(fCompanyId, levelValue));
                        }
                        // 获取公司特殊岗位下的用户
                        usersOfSpecialPosts = userRelationService.getAllUsersOfSpecialPosts(specialPostId, companyIds, 4);
                    } else {
                        Set<String> departmentIds = new HashSet<>();
                        if (levelValue < 0) {
                            //获取发起人公司下所有部门
                            List<XjrBaseDepartment> departmentList = departmentService.list(Wrappers.<XjrBaseDepartment>query().lambda().eq(XjrBaseDepartment::getCompanyId, fCompanyId).eq(XjrBaseDepartment::getEnabledMark, 1).orderByDesc(XjrBaseDepartment::getCreateDate));
                            if (CollectionUtil.isNotEmpty(departmentList)) {
                                departmentIds = departmentList.stream().map(XjrBaseDepartment::getDepartmentId).collect(Collectors.toSet());
                            }
                        } else {
                            // 部门特殊岗位下的用户
                            List<XjrBaseUserRelation> objectsOfUser = userRelationService.getObjectsOfUser(startUserId, 3);
                            for (XjrBaseUserRelation xjrBaseUserRelation : objectsOfUser) {
                                String fDepartmentId = xjrBaseUserRelation.getObjectId();
                                // 获取发起人所属部门上N级
                                departmentIds.add(departmentService.getDepartmentIdByLevel(fDepartmentId, Integer.valueOf(level)));
                            }
                        }
                        usersOfSpecialPosts = userRelationService.getAllUsersOfSpecialPosts(specialPostId, departmentIds, 5);
                    }
                    for (SpecialPostUserVo specialPostUserVo : usersOfSpecialPosts) {
                        userSet.add(specialPostUserVo.getUserId());
                    }
                }
            }
        }
        return userSet;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/12/30
     * @Param:[taskId, userObject]
     * @return:void
     * @Description:根据sql获取用户
     */
    private static Set<String> getUserBySql(String taskId, JSONObject userObject) throws SQLException {
        Set<String> userSet = new HashSet<>();
        List<Task> taskList = taskService.createTaskQuery().taskId(taskId).list();
        String processInstanceId = "";
        if (CollectionUtil.isNotEmpty(taskList)) {
            processInstanceId = taskList.get(0).getProcessInstanceId();
        } else {
            processInstanceId = taskId;
        }
        String fDataSourceId = userObject.getString("F_ObjId");
        JSONArray templateData = userObject.getJSONArray("templateData");
        // 获取流程历史记录
        // 拼接sql
        StringBuffer sql = new StringBuffer();
        for (int i = 0; i < templateData.size(); i++) {
            JSONObject jsonObject = templateData.getJSONObject(i);
            String fieldId = jsonObject.getString("fieldId");
            if (fieldId != null) {
                sql.append(jsonObject.getString("beforeText"));
                // 节点ID
                String resourceId = jsonObject.getString("resourceId");
                String bindTable = jsonObject.getString("bindTable");
                String variableName = resourceId + StringPool.UNDERSCORE + bindTable + StringPool.UNDERSCORE + fieldId;
                HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(variableName).singleResult();
                if (historicVariableInstance != null) {
                    sql.append(historicVariableInstance.getValue());
                }
                String afterText = jsonObject.getString("afterText");
                if (StringUtil.isNotBlank(afterText)) {
                    sql.append(afterText);
                }
            } else {
                String beforeText = jsonObject.getString("beforeText");
                sql.append(beforeText);
                String ceterText = jsonObject.getString("fieldid");
                if (StringUtil.isNotBlank(ceterText)) {
                    sql.append(ceterText);
                }
                String afterText = jsonObject.getString("afterText");
                if (StringUtil.isNotBlank(afterText)) {
                    sql.append(afterText);
                }
            }
        }
        //  执行sql
        List<Entity> maps = dbExecutor.executeQuery(fDataSourceId, sql.toString());
        for (Map<String, Object> sqlMap : maps) {
            Set<String> keySet = sqlMap.keySet();
            for (String key : keySet) {
                if (StringUtil.equalsIgnoreCase("F_UserId", key)) {
                    String fUserId = String.valueOf(sqlMap.get(key));
                    userSet.add(fUserId);
                    break;
                }
            }
        }
        return userSet;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/30
     * @Param:[histList, fObjId]
     * @return:java.util.Set<java.lang.String>
     * @Description:指定节点的限制条件
     */
    private static Set<String> specifyNodeLimitation(List<HistoricActivityInstance> histList, String fObjId) {
        Set<String> userSet = new HashSet<>();
        for (HistoricActivityInstance historicActivityInstance : histList) {
            String resourceId = historicActivityInstance.getActivityId();
            if (StringUtils.equals(resourceId, fObjId)) {
                // 指定节点的审批人
                String assignee = historicActivityInstance.getAssignee();
                if (StringUtils.isNotBlank(assignee)) {
                    userSet.add(assignee);
                } else {
                    // 开始节点的发起人
                    String processInstanceId = historicActivityInstance.getProcessInstanceId();
                    HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
                    if (historicProcessInstance != null) {
                        // 流程发起人
                        String startUserId = historicProcessInstance.getStartUserId();
                        userSet.add(startUserId);
                    }
                }
            }
        }
        return userSet;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/12/29
     * @Param:[taskId, histList, map]
     * @return:void
     * @Description:获取表单字段
     */
    private static Set<String> getFormField(List<HistoricActivityInstance> histList, JSONObject userObject) throws
            Exception {
        Set<String> userSet = new HashSet<>();
        // 节点ID
        String type = userObject.getString("type");
        if (StringUtil.equals(type, "hideComponents")) {   //隐藏组件
            String value = gethideComponentsValue(userObject);
            userSet.addAll(Arrays.asList(value.split(",")));
        } else {
            String resourceId = userObject.getString("resourceId");
            String variableName = resourceId + StringPool.UNDERSCORE + userObject.getString("bindTable") + StringPool.UNDERSCORE + userObject.getString("fieldId");
            // 获取表单字段的值
            for (HistoricActivityInstance historicActivityInstance : histList) {
                if (StringUtils.equals(historicActivityInstance.getActivityId(), resourceId)) {
                    Map<String, Object> variables = runtimeService.getVariables(historicActivityInstance.getProcessInstanceId());
                    if (variables.containsKey(variableName)) {
                        String variableValue = String.valueOf(variables.get(variableName));
                        if (StringUtil.isNotBlank(variableValue)) {
                            String[] userIds = variableValue.split(",");
                            userSet.addAll(Arrays.asList(userIds));
                        }
                    }
                }
            }
        }
        return userSet;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/30
     * @Param:[histList, map]
     * @return:java.util.Set<java.lang.String>
     * @Description:上级领导审批
     */
    private static Set<String> getPostLevelUsers(List<HistoricActivityInstance> histList, JSONObject map) {
        List<XjrBaseUserRelation> postIds = new ArrayList<>();
        Set<String> userSet = new HashSet<>();
        // 上y级领导审批
        String level = map.getString("F_ObjId");
        // 指定节点的上级领导
        if (map.containsKey("resourceId")) {
            // 节点id
            String nodeId = map.getString("resourceId");
            // 找到该节点的审批人
            for (HistoricActivityInstance historicActivityInstance : histList) {
                String resourceId = historicActivityInstance.getActivityId();
                if (StringUtils.equals(resourceId, nodeId)) {
                    // 指定节点的审批人(该节点也有可能是开始节点
                    String assignee = historicActivityInstance.getAssignee();
                    if (StringUtils.isBlank(assignee)) {
                        // 获取该节点的发起人
                        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(historicActivityInstance.getProcessInstanceId()).singleResult();
                        // 获取开始节点的流程发起人
                        assignee = historicProcessInstance.getStartUserId();
                    }
                    // 获取节点审批人的岗位ID集合
                    postIds = userRelationService.getObjectsOfUser(assignee, 2);
                }
            }
        } else {
            // 发起人的上级领导
            // 开始节点的resourceId
            if (CollectionUtil.isNotEmpty(histList)) {
                String processInstanceId = histList.get(0).getProcessInstanceId();
                HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
                // 获取开始节点的流程发起人
                String startUserId = historicProcessInstance.getStartUserId();
                // 获取开始节点发起人的岗位id
                postIds = userRelationService.getObjectsOfUser(startUserId, 2);
            }
        }
        // 获取节点审批人岗位的上N级岗位的人员
        for (XjrBaseUserRelation post : postIds) {
            // 节点审批人的岗位id
            String fPostId = post.getObjectId();
            // 获取审批人岗位ID的第N级的岗位ID
            String postId = postService.getPostIdByLevel(fPostId, Integer.valueOf(level));
            if (postService.getById(postId) != null) {
                // 获取岗位的人员
                if (!StringUtil.equals(postId, "0")) {
                    List<XjrBaseUser> userList = userRelationService.getUsersOfObject(postId, 2);
                    for (XjrBaseUser xjrBaseUser : userList) {
                        String userId = xjrBaseUser.getUserId();
                        userSet.add(userId);
                    }
                }
            }
        }

        return userSet;
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[taskId]
     * @return:java.lang.String[]
     * @Description:读取用户任务的表单key
     */
    public static String[] readTaskForm(String taskId) {
        log.info("【读取用户任务的表单】任务ID:" + taskId);
        String[] taskFormKey = new String[10];
        String taskFormKeyStr = "";
        HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        taskFormKeyStr = historicTaskInstance.getFormKey();
        if (StringUtil.isBlank(taskFormKeyStr)) {
            List<String> list = new ArrayList<>(5);
            String processInstanceId = historicTaskInstance.getProcessInstanceId();
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            String businessKey = historicProcessInstance.getBusinessKey();
            JSONArray array = JSONArray.parseArray(businessKey);
            for (int i = 0; i < array.size(); i++) {
                JSONObject jsonObject = array.getJSONObject(i);
                String formId = jsonObject.getString("F_FormId");
                list.add(formId);
            }
            taskFormKeyStr = list.toString().replace("[", "").replace("]", "");
        }
        if (StringUtils.isNotBlank(taskFormKeyStr)) {
            taskFormKey = taskFormKeyStr.split(",");
        }
        return taskFormKey;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[processInstanceId]
     * @return:com.alibaba.fastjson.JSONArray
     * @Description:获取附件信息
     */
    public static Set<Map<String, Object>> getAnnexInfo(String processInstanceId, String taskId) {
        // 当前登录用户Id
        String currentUserId = SecureUtil.getUserId();
        String businessKey = "";
        String deployId = "";
        Set<Map<String, Object>> resultSet = new HashSet<>();
        // 根据任务id获取流程实例
        HistoricTaskInstance historicTaskInstance = null;
        if (StringUtil.isNotBlank(taskId)) {
            historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).taskId(taskId).singleResult();
        }
        if (historicTaskInstance != null) {
            HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(historicTaskInstance.getProcessInstanceId()).singleResult();
            if (processInstance != null) {
                deployId = processInstance.getDeploymentId();
            }
            List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityId(historicTaskInstance.getTaskDefinitionKey()).list();
            HistoricActivityInstance historicActivityInstance = list.get(0);
            Set<HashMap<String, Object>> nodeSet = new HashSet<>();
            //获取该节点之前的节点
            nodeSet.addAll(getAllNode(historicActivityInstance.getActivityId(), processInstanceId, 2, new TreeSet<>()));
            //获取该节点之后的节点
            nodeSet.addAll(getAllNode(historicActivityInstance.getActivityId(), processInstanceId, 1, new TreeSet<>()));
            businessKey = processInstance.getBusinessKey();
            //获取所有已办的任务
            Set<HistoricTaskInstance> taskInstances = new HashSet<>();
            String startActivitiId = "";
            // 获取表单信息
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
            String nwfSchemeInfoId = processDefinition.getDescription();
            // 获取流程版本
            String version = String.valueOf(processDefinition.getVersion());
            for (HashMap<String, Object> nodeInfo : nodeSet) {
                String activitiId = nodeInfo.get("activitiId").toString();
                String activityType = nodeInfo.get("activityType").toString();
                if (StringUtil.equals(activityType, "startEvent")) {
                    startActivitiId = activitiId;
                    continue;
                }
                taskInstances.addAll(historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).taskDefinitionKey(activitiId).finished().list());
            }
            //获取开始节点的表单信息
            if (StringUtil.equals(processInstance.getStartUserId(), currentUserId)) {
                String key = nwfSchemeInfoId + StringPool.UNDERSCORE + startActivitiId + StringPool.UNDERSCORE + version;
                XjrBaseTempfield startFormInfo = xjrBaseTempfieldService.getByIdAndType(processInstanceId + StringPool.UNDERSCORE + startActivitiId, "25");
                if (startFormInfo != null) {
                    String businessKey1 = startFormInfo.getFvalue();
                    if (StringUtils.isNotBlank(businessKey1)) {
                        JSONArray keyList = JSONObject.parseArray(businessKey1);
                        for (int k = 0; k < keyList.size(); k++) {
                            JSONObject keyMap = keyList.getJSONObject(k);
                            String formId = keyMap.getString("F_FormId");
                            // 查询节点信息
                            resultSet.addAll(getAnnex(key, keyMap, formId, resultSet));
                        }
                    }
                }
            }
            taskInstances.add(historicTaskInstance);
            for (HistoricTaskInstance taskInstance : taskInstances) {
                //获取任务
                ArrayList<String> assignees = nwfTaskMapper.getUserIdByTask(taskInstance.getId());
                if (assignees.contains(currentUserId) || isMultiInstance(taskId)) {
                    // 获取任务表单key
                    String[] formIds = FlowableUtil.readTaskForm(taskInstance.getId());
                    for (String formId : formIds) {
                        if (StringUtils.isNotBlank(businessKey)) {
                            JSONArray keyList = JSONObject.parseArray(businessKey);
                            for (int k = 0; k < keyList.size(); k++) {
                                JSONObject keyMap = keyList.getJSONObject(k);
                                // 表单id相等
                                if (StringUtils.equalsIgnoreCase(keyMap.getString("F_FormId"), formId)) {
                                    // 查询节点信息
                                    String key = nwfSchemeInfoId + StringPool.UNDERSCORE + taskInstance.getTaskDefinitionKey() + StringPool.UNDERSCORE + version;
                                    resultSet.addAll(getAnnex(key, keyMap, formId, resultSet));
                                }
                            }
                        }
                    }
                }
            }
        }
        return resultSet;
    }

    private static Set<Map<String, Object>> getAnnex(String key, JSONObject keyMap, String
            formId, Set<Map<String, Object>> resultSet) {
        XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(key, "3");
        if (xjrBaseTempfield != null) {
            String json = xjrBaseTempfield.getFvalue();
            if (StringUtil.isNotBlank(json)) {
                JSONArray jsonArray = JSON.parseArray(json);
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    if (StringUtil.equals(jsonObject.getString("F_Id"), formId)) {
                        Integer type = jsonObject.getInteger("F_Type");
                        JSONArray childrens = jsonObject.getJSONArray("children");
                        // 获取表单数据
                        String dataId = keyMap.getString("F_Id");
                        Map<String, Object> formData = null;
                        if (type == 0) {
                            formData = formSchemeInfoService.getCustomFormData(formId, dataId);
                        } else {
                            String urlAddress = keyMap.getString("F_UrlAddress");
                            formData = FlowableUtil.getSystemFormData(dataId, urlAddress);
                        }
                        for (int j = 0; j < childrens.size(); j++) {
                            JSONObject children = childrens.getJSONObject(j);
                            String filedsType = children.getString("type");
                            String fieldsName = children.getString("fieldsName");
                            if (StringUtil.equalsIgnoreCase(filedsType, "upload")) {
                                if (children.getBoolean("view")) {
                                    String bindTable = children.getString("bindTable");
                                    String fieldsId = children.getString("fieldsId");
                                    String folderId = "";
                                    if (formData != null) {
                                        Set<Map.Entry<String, Object>> entrySet = formData.entrySet();
                                        for (Map.Entry<String, Object> entry : entrySet) {
                                            // 表名
                                            String tableName = entry.getKey();
                                            // 表单数据
                                            Object object = entry.getValue();
                                            if (object instanceof HashMap) {
                                                // 对象数据类型
                                                HashMap record = (HashMap) object;
                                                Set<Map.Entry<String, Object>> valueEntrySet = record.entrySet();
                                                for (Map.Entry<String, Object> valueEntry : valueEntrySet) {
                                                    String valueKey = valueEntry.getKey();
                                                    Object value = valueEntry.getValue();
                                                    if (StringUtil.equals(tableName, bindTable) && StringUtil.equals(valueKey, fieldsId)) {
                                                        folderId = String.valueOf(value);
                                                    }
                                                }
                                            } else if (object instanceof ArrayList) {
                                                // 数组类型
                                                ArrayList array = (ArrayList) object;
                                                for (int k = 0; k < array.size(); k++) {
                                                    Map<String, Object> map = (HashMap) array.get(k);
                                                    Set<Map.Entry<String, Object>> entrySet1 = map.entrySet();
                                                    for (Map.Entry<String, Object> entry1 : entrySet1) {
                                                        String valueKey = entry1.getKey();
                                                        Object value = entry1.getValue();
                                                        if (StringUtil.equals(tableName, bindTable) && StringUtil.equals(valueKey, fieldsId)) {
                                                            folderId = String.valueOf(value);
                                                        }
                                                    }
                                                }
                                            } else {
                                                if (StringUtil.equals(tableName, fieldsId)) {
                                                    folderId = String.valueOf(object);
                                                }
                                            }
                                        }
                                    }
                                    if (StringUtil.isNotBlank(folderId)) {
                                        List<XjrBaseAnnexesFile> files = annexesFileService.list(Wrappers.<XjrBaseAnnexesFile>query().lambda().eq(XjrBaseAnnexesFile::getFolderId, folderId));
                                        if (CollectionUtil.isNotEmpty(files)) {
                                            for (XjrBaseAnnexesFile file : files) {
                                                Set<String> fileIds = resultSet.stream().map(s -> s.get("fileId").toString()).collect(Collectors.toSet());
                                                if (!fileIds.contains(file.getId())) {
                                                    HashMap<String, Object> annexInfoMap = new HashMap<>();
                                                    annexInfoMap.put("fileId", file.getId());
                                                    annexInfoMap.put("folderId", file.getFolderId());
                                                    annexInfoMap.put("fileName", file.getFileName());
                                                    annexInfoMap.put("filePath", "/annexes-files/" + file.getId());
                                                    String filePath = file.getFilePath().replaceAll(File.separator + File.separator, "//");
                                                  //  String[] split = filePath.split("static");
                                                    //if (split.length > 2) {
                                                      //  annexInfoMap.put("address", split[1]);
                                                    annexInfoMap.put("address", filePath);
                                                    //}
                                                    annexInfoMap.put("fieldsName", fieldsName);
                                                    annexInfoMap.put("fileType", file.getFileType());
                                                    annexInfoMap.put("createTime", file.getCreateDate());
                                                    annexInfoMap.put("createUserName", file.getCreateUserName());
                                                    resultSet.add(annexInfoMap);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return resultSet;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/7
     * @Param:[processInstanceId]
     * @return:void
     * @Description:激活流程
     */
    public static void activateProcessInstance(String processInstanceId) throws Exception {
        log.info("【激活流程】实例ID：" + processInstanceId);
        XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(processInstanceId, "36");
        if (xjrBaseTempfield == null) {
            throw new Exception("流程未被挂起,不能恢复!!");
        }
        runtimeService.activateProcessInstanceById(processInstanceId);
        //添加恢复信息
        JSONObject jsonObject = new JSONObject();
        String userId = SecureUtil.getUserId();
        XjrBaseUser xjrBaseUser = userService.getById(userId);
        jsonObject.put("candidate", StringUtil.isNotBlank(xjrBaseUser.getRealName()) ? xjrBaseUser.getRealName() : xjrBaseUser.getAccount());
        jsonObject.put("candidateUserId", xjrBaseUser.getUserId());
        jsonObject.put("activityType", "activate");
        jsonObject.put("startTime", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        jsonObject.put("endTime", cn.hutool.core.date.DateUtil.now());
        jsonObject.put("time", cn.hutool.core.date.DateUtil.now());
        XjrBaseTempfield xjrBaseTempfield1 = new XjrBaseTempfield();
        xjrBaseTempfield1.setType("42");
        xjrBaseTempfield1.setFvalue(jsonObject.toJSONString());
        xjrBaseTempfield1.setFkey(processInstanceId);
        xjrBaseTempfield1.setCreateTime(new Date());
        xjrBaseTempfieldService.save(xjrBaseTempfield1);
        //删除临时表中的数据
        xjrBaseTempfieldService.removeById(xjrBaseTempfield.getId());
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/9
     * @Param:[]
     * @return:java.lang.Integer
     * @Description:更新流程流水号
     */
    public static synchronized Integer setSerialNumber() {
        //数据库中查流水号
        XjrBaseTempfield one = xjrBaseTempfieldService.getOne(Wrappers.<XjrBaseTempfield>query().lambda()
                .eq(XjrBaseTempfield::getType, "19")
                .orderByDesc(XjrBaseTempfield::getCreateTime)
              ,false
        );
      if(one!=null){
          Integer nwfserialNumber = Integer.valueOf(one.getFvalue());
          nwfserialNumber+=1;
          return nwfserialNumber;
      }
       return 0;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/9
     * @Param:[task, nwfSchemeInfoId]
     * @return:void
     * @Description:脚本任务处理
     */
    private static void scriptTaskHandler(String processInsId, String
            nwfSchemeInfoId, Set<String> actIds) throws Exception {
        XjrNwfScheme xjrNwfScheme = nwfSchemeService.getBySchemeInfoId(nwfSchemeInfoId);
        XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(nwfSchemeInfoId);
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInsId).singleResult();
        XjrBaseTempfield tempKeyValue = xjrBaseTempfieldService.getByIdAndType(nwfSchemeInfoId + "_" + historicProcessInstance.getDeploymentId(), "30");
        HashMap<String, Object> variables = new HashMap<>();
        for (String actId : actIds) {
            //获取脚本任务的参数赋值
            if (xjrNwfScheme != null) {
                String fjson = xjrNwfScheme.getFjson();
                JSONObject jsonObject = JSONObject.parseObject(fjson);
                JSONArray childShapes = jsonObject.getJSONArray("childShapes");
                for (int i = 0; i < childShapes.size(); i++) {
                    JSONObject childShape = childShapes.getJSONObject(i);
                    if (StringUtil.equals(childShape.getString("resourceId"), actId)) {
                        JSONObject properties = childShape.getJSONObject("properties");
                        JSONObject paramOperate = properties.getJSONObject("paramOperate");
                        if (paramOperate != null) {
                            JSONArray parameterAssignments = paramOperate.getJSONArray("parameterAssignment");
                            if (CollectionUtil.isNotEmpty(parameterAssignments)) {
                                for (int j = 0; j < parameterAssignments.size(); j++) {
                                    JSONObject parameterAssignmentObj = parameterAssignments.getJSONObject(j);
                                    JSONObject source = parameterAssignmentObj.getJSONObject("source");
                                    String assignmentType = source.getString("assignmentType");
                                    String variable = "";
                                    String userId = SecureUtil.getUserId();
                                    XjrBaseUser user = userService.getById(userId);
                                    if (StringUtil.equals(assignmentType, "value")) {
                                        //值
                                        variable = source.getString("value");
                                    } else if (StringUtil.equals(assignmentType, "variable")) {
                                        //变量
                                        String type = source.getString("type");
                                        String value = source.getString("value");
                                        variable = getProcessInfo(xjrNwfSchemeinfo, processInsId, type, value, null);
                                    } else if (StringUtil.equals(assignmentType, "sql")) {
                                        //sql
                                        JSONObject tasksql = source.getJSONObject("tasksql");
                                        String database = tasksql.getString("database");
                                        String sql = tasksql.getString("sql");
                                        String field = tasksql.getString("field");
                                        List<Entity> sqlResult = dbExecutor.executeQuery(database, sql);
                                        if (sqlResult.size() > 0) {
                                            //获取第一条数据
                                            Map<String, Object> firstResult = sqlResult.get(0);
                                            Object o = firstResult.get(field);
                                            if (o != null) {
                                                variable = String.valueOf(o);
                                            }
                                        }
                                    } else if (StringUtil.equals(assignmentType, "api")) {
                                        JSONObject taskapi = source.getJSONObject("taskapi");
                                        //参数
                                        JSONArray params = taskapi.getJSONArray("params");
                                        //返回的字段
                                        String field = taskapi.getString("field");
                                        String interfaceId = taskapi.getString("interfaceId");
                                        Map<String, String> paramMap = new HashMap<>();
                                        HttpServletRequest request = WebUtil.getRequest();
                                        for (int k = 0; k < params.size(); k++) {
                                            JSONObject param = params.getJSONObject(k);
                                            String paramValue = param.getString("paramValue");
                                            String paramName = param.getString("paramName");
                                            //参数值的类型
                                            Integer paramValType = param.getInteger("paramValType");
                                            if (paramValType == 1) {
                                                //变量
                                                if (StringUtil.equals(paramValue, "token")) {
                                                    //发起人token
                                                    paramValue = request.getHeader("Authorization");
                                                } else if (StringUtil.equals(paramValue, "userid")) {
                                                    //发起人id
                                                    paramValue = userId;
                                                } else if (StringUtil.equals(paramValue, "username")) {
                                                    //发起人名字
                                                    paramValue = user.getRealName();
                                                } else if (StringUtil.equals(paramValue, "postid")) {
                                                    //发起人岗位id
                                                    List<XjrBaseUserRelation> objectsOfUser = userRelationService.getObjectsOfUser(userId, 2);
                                                    if (CollectionUtil.isNotEmpty(objectsOfUser)) {
                                                        XjrBaseUserRelation xjrBaseUserRelation = objectsOfUser.get(0);
                                                        paramValue = xjrBaseUserRelation.getObjectId();
                                                    }
                                                } else if (StringUtil.equals(paramValue, "companyid")) {
                                                    //发起人公司id
                                                    paramValue = user.getCompanyId();
                                                } else if (StringUtil.equals(paramValue, "departid")) {
                                                    //发起人部门id
                                                    List<XjrBaseUserRelation> objectsOfUser = userRelationService.getObjectsOfUser(userId, 3);
                                                    if (CollectionUtil.isNotEmpty(objectsOfUser)) {
                                                        XjrBaseUserRelation xjrBaseUserRelation = objectsOfUser.get(0);
                                                        paramValue = xjrBaseUserRelation.getObjectId();
                                                    }
                                                } else if (StringUtil.equals(paramValue, "roleid")) {
                                                    //发起人角色id
                                                    List<XjrBaseUserRelation> objectsOfUser = userRelationService.getObjectsOfUser(userId, 1);
                                                    if (CollectionUtil.isNotEmpty(objectsOfUser)) {
                                                        XjrBaseUserRelation xjrBaseUserRelation = objectsOfUser.get(0);
                                                        paramValue = xjrBaseUserRelation.getObjectId();
                                                    }
                                                }
                                            }
                                            paramMap.put(paramName, paramValue);
                                        }
                                        MediaType JSONType = MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE);
                                        okhttp3.RequestBody body = okhttp3.RequestBody.create(JSONType, JSON.toJSONString(paramMap));
                                        String host = serverConfig.getLocalUrl();
                                        String address = host + StringPool.SLASH + "xjr-interface-info" + StringPool.SLASH + "execute" + StringPool.SLASH + interfaceId;
                                        OkHttpClient client = new OkHttpClient();
                                        HttpUrl parse = HttpUrl.parse(address);
                                        HttpUrl.Builder builder = Objects.requireNonNull(parse).newBuilder();
                                        Request.Builder url = new Request.Builder().url(builder.build());
                                        url.addHeader("isWorkFlow", "true");
                                        url.addHeader("Authorization", request.getHeader("Authorization"));
                                        Request req = url.post(body).build();
                                        okhttp3.Response response = client.newCall(req).execute();
                                        if (response.isSuccessful()) {
                                            String responseBody = Objects.requireNonNull(response.body()).string();
                                            JSONObject responseBodyObj = JSONObject.parseObject(responseBody);
                                            if (responseBodyObj.getBoolean("success")) {
                                                JSONObject data = responseBodyObj.getJSONObject("data");
                                                if (CollectionUtil.isNotEmpty(data)) {
                                                    Object o = data.get(field);
                                                    if (o != null) {
                                                        variable = String.valueOf(o);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    String id = parameterAssignmentObj.getJSONObject("target").getString("id");
                                    variables.put(id, variable);
                                }
                            }
                        }
                    }
                }
            }
            List<XjrBaseTempfield> list = xjrBaseTempfieldService.list(Wrappers.<XjrBaseTempfield>query().lambda().eq(XjrBaseTempfield::getFkey, actId).eq(XjrBaseTempfield::getType, "20"));
            Boolean record = false;
            String nodeName = "";
            JSONArray jsonArray = new JSONArray();
            if (tempKeyValue != null) {
                String fvalue = tempKeyValue.getFvalue();
                JSONArray childShapes = JSONObject.parseObject(fvalue).getJSONArray("childShapes");
                for (int i = 0; i < childShapes.size(); i++) {
                    JSONObject childShape = childShapes.getJSONObject(i);
                    if (StringUtil.equals(childShape.getString("resourceId"), actId)) {
                        record = childShape.getJSONObject("properties").getBoolean("record");
                        nodeName = childShape.getJSONObject("properties").getString("name");
                    }
                }
            }
            if (list.size() > 0) {
                for (XjrBaseTempfield xjrBaseTempfield : list) {
                    String myVar = xjrBaseTempfield.getFvalue();
                    if (StringUtil.isNotBlank(myVar) && !StringUtil.equals("[]", myVar)) {
                        JSONArray retArray = JSONArray.parseArray(myVar);
                        for (int i = 0; i < retArray.size(); i++) {
                            JSONObject jsonObject = JSONObject.parseObject(retArray.getString(i));
                            String type = jsonObject.getString("type");
                            JSONObject scriptText = scriptHandler(processInsId, nwfSchemeInfoId, jsonObject, type);
                            jsonArray.add(scriptText);
                        }
                    }
                }
            }
            if (record != null && record) {
                String scriptTexts = StringPool.SPACE + StringPool.LEFT_SQ_BRACKET + nodeName + StringPool.RIGHT_SQ_BRACKET;
                if (CollectionUtil.isEmpty(jsonArray)) {
                    scriptTexts = scriptTexts + "执行成功";
                } else {
                    for (int i = 0; i < jsonArray.size(); i++) {
                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        String scriptType = jsonObject.getString("scriptType");
                        String scripttext = jsonObject.getString("scripttext");
                        boolean sucess = jsonObject.getBoolean("sucess");
                        scriptTexts = scriptTexts + "执行了";
                        if (StringUtil.equalsIgnoreCase(scriptType, "script") || StringUtil.equalsIgnoreCase(scriptType, "taskScriptObj")) {
                            scriptTexts = scriptTexts + "脚本";
                        } else if (StringUtil.equalsIgnoreCase(scriptType, "api") || StringUtil.equalsIgnoreCase(scriptType, "taskApiObj")) {
                            scriptTexts = scriptTexts + "API";
                        } else {
                            scriptTexts = scriptTexts + "SQL";
                        }
                        scriptTexts = scriptTexts + StringPool.SINGLE_QUOTE + scripttext + StringPool.SINGLE_QUOTE;
                        if (sucess) {
                            scriptTexts = scriptTexts + "成功";
                        } else {
                            scriptTexts = scriptTexts + "失败";
                        }
                        scriptTexts = scriptTexts + StringPool.SEMICOLON;
                    }
                }
                XjrBaseTempfield xjrBaseTempfield = new XjrBaseTempfield();
                xjrBaseTempfield.setFkey(processInsId + StringPool.UNDERSCORE + actId);
                xjrBaseTempfield.setFvalue(scriptTexts);
                xjrBaseTempfield.setType("37");
                xjrBaseTempfield.setCreateTime(new Date());
                xjrBaseTempfieldService.save(xjrBaseTempfield);
            }
        }
        if (historicProcessInstance.getEndTime() == null && CollectionUtil.isNotEmpty(variables)) {
            runtimeService.setVariables(processInsId, variables);
        }
    }

    //脚本任务处理
    private static JSONObject scriptHandler(String processInsId, String nwfSchemeInfoId, JSONObject
            scriptInfo, String scriptType) throws Exception {
        boolean sucess = false;
        String scripttext = "";
        XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(nwfSchemeInfoId);
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInsId).singleResult();
        String startUserId = historicProcessInstance.getStartUserId();
        XjrBaseUser user = userService.getById(startUserId);
        if (StringUtil.equalsIgnoreCase(scriptType, "script") || StringUtil.equalsIgnoreCase(scriptType, "taskScriptObj")) {
            // 脚本执行
            String scriptformat = scriptInfo.getString("scriptformat");
            if (StringUtils.equalsIgnoreCase(scriptformat, "JavaScript")) {
                String jsText = scriptInfo.getString("scripttext");
                scripttext = jsText;
                sucess = true;
            }
        } else if (StringUtil.equalsIgnoreCase(scriptType, "api") || StringUtil.equalsIgnoreCase(scriptType, "taskApiObj")) {
            // api
            JSONArray apitext = new JSONArray();
            JSONArray iframeData = scriptInfo.getJSONArray("iframeData");
            for (int j = 0; j < iframeData.size(); j++) {
                JSONObject jsonObject = iframeData.getJSONObject(j);
                // 构建请求参数
                JSONArray params = jsonObject.getJSONArray("params");
                String interfaceId = jsonObject.getString("interfaceId");
                scripttext = jsonObject.getString("apiUrl");
                HttpServletRequest request = WebUtil.getRequest();
                Map<String, String> requestParms = new HashMap<>();
                for (int p = 0; p < params.size(); p++) {
                    JSONObject paramObject = params.getJSONObject(p);
                    String paramName = paramObject.getString("paramName");
                    Integer paramValType = paramObject.getInteger("paramValType");
                    String paramValue = paramObject.getString("paramValue");
                    if (paramValType == 1) {
                        //发起人信息
                        if (StringUtil.equals(paramValue, "userid")) {
                            paramValue = startUserId;
                        } else if (StringUtil.equals(paramValue, "companyid")) {
                            //发起人公司id
                            paramValue = user.getCompanyId();
                        } else if (StringUtil.equals(paramValue, "departid")) {
                            //发起人部门id
                            List<XjrBaseUserRelation> objectsOfUser = userRelationService.getObjectsOfUser(startUserId, 3);
                            if (CollectionUtil.isNotEmpty(objectsOfUser)) {
                                XjrBaseUserRelation xjrBaseUserRelation = objectsOfUser.get(0);
                                paramValue = xjrBaseUserRelation.getObjectId();
                            }
                        }
                    } else if (paramValType == 2 || paramValType == 3) {
                        //表单数据或流程参数
                        JSONObject paramJson = paramObject.getJSONObject("paramJson");
                        if (CollectionUtil.isNotEmpty(paramJson)) {
                            paramValue = gethideComponentsValue(paramJson);
                        }
                        HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInsId).variableName(paramValue).singleResult();
                        if (variableInstance != null) {
                            paramValue = String.valueOf(variableInstance.getValue());
                        }
                    }
                    requestParms.put(paramName, paramValue);
                }
                try {
                    MediaType JSONType = MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE);
                    okhttp3.RequestBody body = okhttp3.RequestBody.create(JSONType, JSON.toJSONString(requestParms));
                    String host = serverConfig.getLocalUrl();
                    String address = host + StringPool.SLASH + "xjr-interface-info" + StringPool.SLASH + "execute" + StringPool.SLASH + interfaceId;
                    OkHttpClient client = new OkHttpClient();
                    HttpUrl parse = HttpUrl.parse(address);
                    HttpUrl.Builder builder = Objects.requireNonNull(parse).newBuilder();
                    Request.Builder url = new Request.Builder().url(builder.build());
                    url.addHeader("isWorkFlow", "true");
                    url.addHeader("Authorization", request.getHeader("Authorization"));
                    Request req = url.post(body).build();
                    okhttp3.Response response = client.newCall(req).execute();
                    if (response.isSuccessful()) {
                        String responseBody = Objects.requireNonNull(response.body()).string();
                        JSONObject responseBodyObj = JSONObject.parseObject(responseBody);
                        if (responseBodyObj.getBoolean("success")) {
                            JSONObject data = responseBodyObj.getJSONObject("data");
                            sucess = true;
                            apitext.add(data);
                        }
                    }
//                    Response execute = infoService.execute(interfaceId, requestParms, request);
//                    if (execute.isSuccess()) {
//                        apitext.add((HashMap<String, Object>) (execute.getData()));
//                        sucess = true;
//                    }
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            }
        } else {
            // sql
            JSONObject iframeData = scriptInfo.getJSONObject("iframeData");
            scripttext = iframeData.getString("sql");
            JSONArray templateData = iframeData.getJSONArray("templateData");
            String fDataSourceId = iframeData.getString("F_ObjId");
            String sql = "";
            // 添加参数
            for (int j = 0; j < templateData.size(); j++) {
                JSONObject object = templateData.getJSONObject(j);
                String beforeText = object.getString("beforeText");
                if (StringUtil.isNotBlank(beforeText)) {
                    sql = sql + object.getString("beforeText");
                }
                String infoValue = object.getString("id");
                String infoType = object.getString("type");
                String resourceId = object.getString("resourceId");
                String bindTable = object.getString("bindTable");
                String param = object.getString("value");
                if (StringUtil.equalsIgnoreCase(infoType, "condition")) {
                    if (infoValue != null && (!StringUtil.equals("", infoValue))) {
                        infoValue = resourceId + StringPool.UNDERSCORE + bindTable + StringPool.UNDERSCORE + infoValue;
                    }
                }
                if (StringUtil.equalsIgnoreCase(infoType, "hideComponents")) {
                    param = gethideComponentsValue(object);
                } else if (infoType != null) {
                    param = getProcessInfo(xjrNwfSchemeinfo, processInsId, infoType, infoValue, null);
                }
                if (StringUtil.isNotBlank(param)) {
                    sql = sql + param;
                }
                String afterText = object.getString("afterText");
                if (StringUtil.isNotBlank(afterText)) {
                    sql = sql + afterText;
                }
            }
//            sql = StringUtil.replace(sql, StringPool.NEWLINE, StringPool.EMPTY);
            //获取sql类型
            if (sql.length() > 5) {
                String sqlType = sql.substring(0, 6);
                List<Entity> sqltext = new ArrayList<>();
                //执行sql
                try {
                    if (StringUtil.equalsIgnoreCase("select", sqlType)) {
                        sqltext = dbExecutor.executeQuery(fDataSourceId, sql);
                    } else {
                        dbExecutor.executeUpdate(fDataSourceId, sql);
                    }
                    sucess = true;
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            }
        }
        JSONObject result = new JSONObject();
        result.put("scriptType", scriptType);
        result.put("scripttext", scripttext);
        result.put("sucess", sucess);
        return result;
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/9
     * @Param:[processInstanceId, deploymentId]
     * @return:void
     * @Description:判断下个任务节点是否有添加候选人，有则将任务指派给用户
     */
    private static List<Task> delegateUsers(String processInstanceId, String deploymentId) {
        // 判断下个任务节点是否有添加候选人
        // 获取流程模板id
        List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getByDeploymentId(deploymentId);
        if (xjrNwfSchemeinfo != null) {
            String schemeInfoId = xjrNwfSchemeinfo.getId();
            // 判断该流程模板是否有委托人
            List<XjrNwfDelegaterelation> relationList = nwfDelegateRelationService.getBySchemeInfoId(schemeInfoId);
            if (!Collections.isEmpty(relationList)) {
                // 判断当前时间是否在委托时间内
                for (XjrNwfDelegaterelation xjrNwfDelegaterelation : relationList) {
                    XjrNwfDelegateRule xjrNwfDelegaterule = delegateruleService.getById(xjrNwfDelegaterelation.getDelegateRuleId());
                    // 结束时间
                    LocalDateTime fEnddate = xjrNwfDelegaterule.getEndDate();
                    // 开始时间
                    LocalDateTime fCreatedate = xjrNwfDelegaterule.getBeginDate();
                    // 委托人ID
                    String fCreateuserid = xjrNwfDelegaterule.getCreateUserId();
                    // 被委托人ID
                    String toUserId = xjrNwfDelegaterule.getToUserId();
                    // 当前时间
                    LocalDateTime currentDate = LocalDateTime.now();
                    if (currentDate.isAfter(fCreatedate) && currentDate.isBefore(fEnddate)) {
                        // 获取下一个任务
//                        Task nextTask = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
                        for (Task task : list) {
                            if (task != null) {
                                // 获取下一个任务候选人
                                List<HistoricIdentityLink> userList = historyService.getHistoricIdentityLinksForTask(task.getId());
                                Set<String> userSet = userList.stream().map(s -> s.getUserId()).collect(Collectors.toSet());
                                String[] split = toUserId.split(StringPool.COMMA);
                                JSONArray userIds = new JSONArray();
                                for (String userId : split) {
                                    if (userSet.contains(fCreateuserid) && (!userSet.contains(userId))) {
                                        taskService.addCandidateUser(task.getId(), userId);
                                        userIds.add(userId);
                                    }
                                }
                                if (CollectionUtil.isNotEmpty(userIds)) {
                                    //添加委托信息
                                    JSONObject delegateObj = new JSONObject();
                                    delegateObj.put("createUserId", fCreateuserid);
                                    delegateObj.put("delegateUsers", userIds);
                                    XjrBaseTempfield xjrBaseTempfield = new XjrBaseTempfield();
                                    xjrBaseTempfield.setFkey(task.getId());
                                    xjrBaseTempfield.setType("40");
                                    xjrBaseTempfield.setFvalue(delegateObj.toJSONString());
                                    xjrBaseTempfield.setCreateTime(new Date());
                                    xjrBaseTempfieldService.save(xjrBaseTempfield);
                                }
//                                for (int i = 0; i < userList.size(); i++) {
//                                    String userType = userList.get(i).getType();
//                                    String userId = userList.get(i).getUserId();
//                                    String groupId = userList.get(i).getGroupId();
//                                    if ("candidate".equals(userType)) {
//                                        if (StringUtils.isNotBlank(userId)) {
//                                            // 如果委托人ID等于候选人
//                                            if (StringUtils.equals(fCreateuserid, userList.get(i).getUserId())) {
//                                                // 添加指定候选人
//                                                String[] split = toUserId.split(StringPool.COMMA);
//                                                for (String deleteUserId : split) {
//                                                    taskService.addCandidateUser(task.getId(), deleteUserId);
//                                                }
//                                            }
//                                        } else if (StringUtils.isNotBlank(groupId)) {
//                                            // 查询角色下的所有人员
//                                            List<XjrBaseUser> roleUserList = userRelationService.getUsersOfObject(groupId, 1);
//                                            if (!Collections.isEmpty(roleUserList)) {
//                                                for (XjrBaseUser user : roleUserList) {
//                                                    String fUserId = user.getUserId();
//                                                    // 如果委托人ID等于候选人
//                                                    if (StringUtils.equals(fCreateuserid, fUserId)) {
//                                                        // 添加指定候选人
//                                                        taskService.addCandidateUser(task.getId(), toUserId);
//                                                    }
//                                                }
//                                            }
//                                        }
//                                    }
//                                }
                            }
                        }
                    }
                }
            }
        }
        return list;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/10
     * @Param:[processInstanceId]
     * @return:boolean
     * @Description:流程实例放入回收站
     */
    public static boolean toRecycleBin(String processInstanceId) throws Exception {
        String fName = "";
        String processDefinitionId = "";
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        // 进行中的流程
        if (processInstance != null) {
            processDefinitionId = processInstance.getProcessDefinitionId();
            // 挂起流程
            FlowableUtil.suspendProcessInstance(processInstanceId, "流程被放入回收站", 0);
        } else {
            HistoricProcessInstance hisProcessInstanceId = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            if (hisProcessInstanceId.getEndTime() != null) {
                throw new Exception("流程已结束不能放入回收站!!!!");
            }
            processDefinitionId = hisProcessInstanceId.getProcessDefinitionId();
        }
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        if (processDefinition != null) {
            String nwfSchemeInfoId = processDefinition.getDescription();
            XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(nwfSchemeInfoId);
            if (xjrNwfSchemeinfo != null) {
                fName = xjrNwfSchemeinfo.getName();
            }
        }
        // 存入temp表
        XjrBaseTempfield xjrTempKeyvalue = new XjrBaseTempfield();
        xjrTempKeyvalue.setId(IdWorker.get32UUID());
        xjrTempKeyvalue.setFkey(processInstanceId);
        xjrTempKeyvalue.setFvalue(fName);
        xjrTempKeyvalue.setType("18");
        return xjrBaseTempfieldService.save(xjrTempKeyvalue);
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/10
     * @Param:[pnum, psize, fName]
     * @return:java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
     * @Description:查询回收站
     */
    public static Object selectRecycleBin(GetPageListNwfTaskDto dto) {
        List<Map<String, Object>> retList = new ArrayList<>();
        String nwfRelationId = dto.getNwfRelationId();
        JSONArray definitionKeys = nwfRelationService.getNwfSchemeInfoIds(nwfRelationId);
        String serialNumber = dto.getSerialNumber();
        String queryParameter = dto.getQueryParameter();
        List<XjrBaseUser> xjrBaseUserList = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.USER_LIST_CACHE_KEY);
        Page<XjrBaseTempfield> page = nwfTaskMapper.selectRecycleBin(new Page(dto.getLimit(), dto.getSize()), dto.getStartTime(), dto.getEndTime(), dto.getKeyword(), SecureUtil.getUserId(), definitionKeys);
        List<XjrBaseTempfield> xjrBaseTempfieldList = xjrBaseTempfieldService.list(Wrappers.<XjrBaseTempfield>query().lambda().eq(XjrBaseTempfield::getType, "19"));
        boolean flag = StringUtil.isNotBlank(nwfRelationId) && "false".equals(nwfRelationService.getPageInfoById(nwfRelationId).getString("isPage"));
        List<XjrBaseTempfield> list = new ArrayList<>();
        if (flag) {
            //不分页
            list = nwfTaskMapper.selectAllRecycleBin(dto.getStartTime(), dto.getEndTime(), dto.getKeyword(), SecureUtil.getUserId(), definitionKeys);
        } else {
            list = page.getRecords();
        }
        if (CollectionUtil.isEmpty(list)) {
            return null;
        }
        // 专项菜单字段
        JSONArray formFields = nwfRelationService.getFormFieldById(nwfRelationId);
        JSONArray searchFields = nwfRelationService.getSearchFieldById(nwfRelationId, queryParameter);
        // 验证专项菜单模板权限
        if (!nwfRelationService.checkTemplateAuthority(nwfRelationId, SecureUtil.getUserId())) {
            return ConventPage.getPageOutput(page);
        }
        Set<String> keys = list.stream().map(XjrBaseTempfield::getFkey).collect(Collectors.toSet());
        List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().processInstanceIds(keys).list();
        List<Task> taskList = taskService.createTaskQuery().processInstanceIdIn(new ArrayList<>(keys)).list();
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceIdIn(new ArrayList<>(keys)).list();
        List<ProcessDefinition> processDefinitionList = repositoryService.createProcessDefinitionQuery().list();
        List<XjrNwfSchemeinfo> xjrNwfSchemeinfoList = nwfSchemeInfoService.list();
        for (XjrBaseTempfield xjrBaseTempfield : list) {
            String processDefinitionId = "";
            Date startTime = null;
            String startUserId = "";
            int priority = 0;
            String taskName = "";
            String taskId = "";
            String schemeName = "";
            Map<String, Object> map = new HashMap<>(16);
            String processInstanceId = xjrBaseTempfield.getFkey();
            // 任务发起人
            Optional<ProcessInstance> processInstanceOptional = processInstanceList.stream().filter(x -> x.getProcessInstanceId().equals(processInstanceId) && StringUtil.isNotBlank(x.getStartUserId())).findFirst();
            if (processInstanceOptional.isPresent()) {
                ProcessInstance processInstance = processInstanceOptional.get();
                processDefinitionId = processInstance.getProcessDefinitionId();
                startTime = processInstance.getStartTime();
                startUserId = processInstance.getStartUserId();
                schemeName = processInstance.getName();
                // 任务查询
                Optional<Task> firstTask = taskList.stream().filter(x -> x.getProcessInstanceId().equals(processInstanceId)).findFirst();
                if (firstTask.isPresent()) {
                    Task currentTask = firstTask.get();
                    // 任务名称
                    taskName = currentTask.getName();
                    // 任务等级
                    priority = currentTask.getPriority();
                    // 任务ID
                    taskId = currentTask.getId();
                }
                map.put("processStatus", "进行中");
            } else {
                HistoricProcessInstance hisProcess = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
                if (hisProcess != null) {
                    processDefinitionId = hisProcess.getProcessDefinitionId();
                    startTime = hisProcess.getStartTime();
                    startUserId = hisProcess.getStartUserId();
                    schemeName = hisProcess.getName();
                }
                // 任务查询
                List<HistoricTaskInstance> hiTaskList = historicTaskInstanceList.stream().sorted(Comparator.comparing(HistoricTaskInstance::getStartTime)).filter(x -> x.getProcessInstanceId().equals(processInstanceId)).collect(Collectors.toList());
                if (!hiTaskList.isEmpty()) {
                    HistoricTaskInstance hisTask = hiTaskList.get(hiTaskList.size() - 1);
                    taskName = hisTask.getName();
                    taskId = hisTask.getId();
                    priority = hisTask.getPriority();
                }
                map.put("processStatus", "已结束");
            }
            // 获取专项菜单字段
            JSONObject formFieldObj = new JSONObject();
            if (nwfRelationId != null) {
                if (nwfRelationService.checkFieldAuthority(nwfRelationId, SecureUtil.getUserId(), xjrBaseUserList)) {
                    for (int j = 0; j < formFields.size(); j++) {
                        JSONObject formField = formFields.getJSONObject(j);
                        String fieldName = formField.getString("resourceId") + com.baomidou.mybatisplus.core.toolkit.StringPool.UNDERSCORE +
                                formField.getString("bindTable") + com.baomidou.mybatisplus.core.toolkit.StringPool.UNDERSCORE +
                                formField.getString("fieldsId");
                        HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().variableName(fieldName).processInstanceId(processInstanceId).singleResult();
                        formFieldObj.put(formField.getString("name"), historicVariableInstance != null ? historicVariableInstance.getValue() : "");
                    }
                    //添加搜索字段值‘
                    for (int j = 0; j < searchFields.size(); j++) {
                        JSONObject searchField = searchFields.getJSONObject(j);
                        String fieldName = searchField.getString("resourceId") +
                                StringPool.UNDERSCORE + searchField.getString("bindTable") +
                                StringPool.UNDERSCORE + searchField.getString("field");
                        String name = searchField.getString("name");
                        if (!formFieldObj.keySet().contains(name)) {
                            List<HistoricVariableInstance> historicVariableInstance = historyService.createHistoricVariableInstanceQuery().variableName(fieldName).processInstanceId(processInstanceId).list();
                            for (HistoricVariableInstance variableInstance : historicVariableInstance) {
                                formFieldObj.put(name, variableInstance != null ? variableInstance.getValue() : "");
                            }
                        }
                    }
                }
            }
            map.put("formFieldObj", formFieldObj);
            map.put("createTime", startTime != null ? DateUtil.format(startTime, "yyyy-MM-dd HH:mm:ss") : "");
            map.put("taskName", taskName);
            map.put("taskId", taskId);
            map.put("priority", priority);
            map.put("processInstanceId", processInstanceId);
            //流水号
            Optional<XjrBaseTempfield> xjrBaseTempfieldOptional = xjrBaseTempfieldList.stream().filter(x -> x.getFkey().equals(processInstanceId)).findFirst();
            if (xjrBaseTempfieldOptional.isPresent()) {
                map.put("serialNumber", xjrBaseTempfieldOptional.get().getFvalue());
            }
            // 流程模板名称
            String finalProcessDefinitionId = processDefinitionId;
            Optional<ProcessDefinition> processDefinitionOptional = processDefinitionList.stream().filter(x -> x.getId().equals(finalProcessDefinitionId)).findFirst();
            if (StringUtil.isBlank(schemeName) && processDefinitionOptional.isPresent()) {
                String nwfSchemeInfoId = processDefinitionOptional.get().getDescription();
                Optional<XjrNwfSchemeinfo> xjrNwfSchemeinfoOptional = xjrNwfSchemeinfoList.stream().filter(x -> x.getId().equals(nwfSchemeInfoId)).findFirst();
                if (xjrNwfSchemeinfoOptional.isPresent()) {
                    schemeName = xjrNwfSchemeinfoOptional.get().getName();
                }
            }
            map.put("schemeName", schemeName);
            // 发起人
            String userId = startUserId;
            Optional<XjrBaseUser> xjrBaseUserOptional = xjrBaseUserList.stream().filter(x -> StringUtil.equals(x.getUserId(), userId)).findFirst();
            if (xjrBaseTempfieldOptional.isPresent()) {
                XjrBaseUser startUser = xjrBaseUserOptional.get();
                map.put("startUser", startUser.getRealName());
            } else {
                map.put("startUser", "");
            }
            retList.add(map);
        }
        java.util.Collections.sort(retList, (s1, s2) -> s2.get("createTime").toString().compareTo(s1.get("createTime").toString()));
        if (StringUtil.isNotBlank(serialNumber)) {
            Pattern pattern = Pattern.compile(serialNumber);
            retList = retList.stream().filter(s -> {
                Matcher matcher = pattern.matcher(s.get("serialNumber").toString());
                //调用模糊查询方法
                if (matcher.find()) {
                    return true;
                } else {
                    return false;
                }
            }).collect(Collectors.toList());
        }
        //自定义查询条件
        if (StringUtil.isNotBlank(queryParameter)) {
            JSONObject queryParameterJson = JSONObject.parseObject(queryParameter);
            if (queryParameter != null) {
                Set<Map.Entry<String, Object>> entries = queryParameterJson.entrySet();
                for (Map.Entry<String, Object> entry : entries) {
                    String key = entry.getKey();
                    Object valueObj = entry.getValue();
                    String value = String.valueOf(valueObj);
                    if (StringUtil.endsWithIgnoreCase(key, "_Start")) {
                        //为时间范围查询
                        String field = key.split("_Start")[0];
                        String avueType = "";
                        for (int i = 0; i < searchFields.size(); i++) {
                            JSONObject searchFieldsObj = searchFields.getJSONObject(i);
                            if (StringUtil.equals(searchFieldsObj.getString("name"), field)) {
                                avueType = searchFieldsObj.getJSONObject("componentConfig").getJSONObject("__config__").getString("avueType");
                                break;
                            }
                        }
                        //获取结束时间
                        Optional<Map.Entry<String, Object>> endOptional = entries.stream().filter(s -> StringUtil.equalsIgnoreCase(s.getKey(), field + "_End")).findFirst();
                        if (endOptional.isPresent()) {
                            Map.Entry<String, Object> endEntry = endOptional.get();
                            Object endValueObj = endEntry.getValue();
                            if (StringUtil.equals(avueType, "time") || StringUtil.equals(avueType, "datetime")) {
                                String format = StringUtil.equals(avueType, "time") ? DatePattern.NORM_TIME_PATTERN : DatePattern.NORM_DATE_PATTERN;
                                //时间选择
                                retList = retList.stream().filter(s -> {
                                    String formfilevalue = ((JSONObject) (s.get("formFieldObj"))).getString(field);
                                    DateTime date = cn.hutool.core.date.DateUtil.parse(formfilevalue, format);
                                    DateTime startTime = cn.hutool.core.date.DateUtil.parse(value, format);
                                    DateTime endTime = cn.hutool.core.date.DateUtil.parse(String.valueOf(endValueObj), format);
                                    return date.after(startTime) && date.before(endTime);
                                }).collect(Collectors.toList());
                            }
                        }
                    } else if (!StringUtil.endsWithIgnoreCase(key, "_End") && value != null && (!StringUtil.equals(value, "null"))) {
                        Pattern pattern = Pattern.compile(value);
                        retList = retList.stream().filter(s -> {
                            Object formFieldObj = s.get("formFieldObj");
                            if (formFieldObj != null) {
                                String formfilevalue = ((JSONObject) formFieldObj).getString(key);
                                Matcher matcher = pattern.matcher(formfilevalue == null ? "" : formfilevalue);
                                //调用模糊查询方法
                                if (matcher.find()) {
                                    return true;
                                } else {
                                    return false;
                                }
                            } else {
                                return true;
                            }
                        }).collect(Collectors.toList());
                    }
                }
            }
        }
        Map<String, List<Object>> fieldValueListMap = new CaseInsensitiveKeyMap<>();
        for (Map<String, Object> map : retList) {
            JSONObject formFieldObj = (JSONObject) map.get("formFieldObj");
            for (Map.Entry<String, Object> entry : formFieldObj.entrySet()) {
                Object value = entry.getValue();
                if (StringUtil.isEmpty(value)) {
                    continue;
                }
                if (value instanceof NCLOB) {
                    try {
                        value = ((NCLOB) value).stringValue();
                    } catch (SQLException e) {
                        log.error("NCLOB类型数据序列化失败！", e);
                    }
                }
                String key = entry.getKey();
                List<Object> values = fieldValueListMap.get(key);
                if (values == null) {
                    values = new ArrayList<>();
                    fieldValueListMap.put(key, values);
                }
                values.add(value);
            }
        }
        Map<String, Map<String, Object>> dataMap = new HashMap<>(16);
        Map<String, String> multiValueSeparatorMap = new HashMap<>();
        for (Object formField : formFields) {
            JSONObject field = (JSONObject) formField;
            JSONObject componentConfig = field.getJSONObject(FormConstants.COMPONENTCONFIG);
            String fieldName = MapUtils.getString(field, FormConstants.DB_TABLE_NAME);
            if (componentConfig != null) {
                FormDataUtil.buildFieldData(dataMap, multiValueSeparatorMap, componentConfig, fieldValueListMap, fieldName);
            }
        }
        for (Map<String, Object> map : retList) {
            JSONObject formFieldObj = (JSONObject) map.get("formFieldObj");
            for (String fieldName : dataMap.keySet()) {
                Object value = formFieldObj.get(fieldName);
                if (value instanceof CLOB) {
                    try {
                        value = ((NCLOB) value).stringValue();
                    } catch (SQLException e) {
                        log.error("NCLOB类型数据序列化失败！", e);
                    }
                } else {
                    value = StringUtil.isEmpty(formFieldObj.get(fieldName)) ? null : String.valueOf(value);
                }
                Map<String, Object> data = dataMap.get(fieldName);
                if (data == null || StringUtil.isEmpty(value)) {
                    continue;
                }
                Object transToValue = null;
                if (multiValueSeparatorMap.keySet().contains(fieldName)) {
                    String[] values = StringUtils.split(String.valueOf(value), StringPool.COMMA);
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < values.length; i++) {
                        Object obj = data.get(values[i]);
                        if (obj != null) {
                            if (i != 0) {
                                sb.append(multiValueSeparatorMap.get(fieldName));
                            }
                            sb.append(obj);
                        }
                    }
                    transToValue = sb.toString();
                } else {
                    transToValue = data.get(value);
                }
                if (!(transToValue == null || "".equals(transToValue))) {
                    formFieldObj.put(fieldName, transToValue);
                }
            }
        }
        if (flag) {
            //不分页
            return retList;
        }
        PageOutput pageOutput = new PageOutput();
        pageOutput.setRows(retList);
        pageOutput.setTotal((int) page.getTotal());
        return pageOutput;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/10
     * @Param:[processInstanceId]
     * @return:boolean
     * @Description:删除流程实例
     */
    public static boolean deleteProcessInstance(String processInstanceId) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        // 删除工作流表中的数据
        if (processInstance != null) {
            runtimeService.deleteProcessInstance(processInstanceId, "删除");
        } else {
            HistoricProcessInstance hisProcessInStance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            if (hisProcessInStance != null) {
                String hisProcessInstanceId = hisProcessInStance.getId();
                historyService.deleteHistoricProcessInstance(hisProcessInstanceId);
            } else {
                log.info("该流程实例不存在!");
                return false;
            }
        }
        // 删除temp表中的数据
        QueryWrapper<XjrBaseTempfield> query = new QueryWrapper<>();
        query.lambda().like(XjrBaseTempfield::getFkey, processInstanceId);
        xjrBaseTempfieldService.remove(query);
        return true;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/10
     * @Param:[processInstanceId]
     * @return:com.alibaba.fastjson.JSONObject
     * @Description:重新发起
     */
    public static JSONObject reinitiate(String processInstanceId) {
        JSONObject retObj = new JSONObject();
        JSONArray retAry = new JSONArray();
        String businessKey = "";
        String nwfSchemeInfoId = "";
        String deploymentId = "";
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (processInstance != null) {
            deploymentId = processInstance.getDeploymentId();
            businessKey = processInstance.getBusinessKey();
            String processDefinitionId = processInstance.getProcessDefinitionId();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
            if (processDefinition != null) {
                nwfSchemeInfoId = processDefinition.getDescription();
            }
        } else {
            HistoricProcessInstance hisProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            deploymentId = hisProcessInstance.getDeploymentId();
            businessKey = hisProcessInstance.getBusinessKey();
            String processDefinitionId = hisProcessInstance.getProcessDefinitionId();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
            if (processDefinition != null) {
                nwfSchemeInfoId = processDefinition.getDescription();
            }
        }
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        //获取开始节点填的表单数据
        JSONArray formInfoArray = new JSONArray();
        if (historicProcessInstance != null) {
            List<HistoricVariableInstance> list = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(historicProcessInstance.getStartActivityId() + StringPool.UNDERSCORE + "formData").list();
            if (CollectionUtil.isNotEmpty(list)) {
                Object formData = list.get(0).getValue();
                if (formData != null) {
                    formInfoArray = (JSONArray) formData;
                }
            }
        }
        //开始节点信息
        String startNodeInfo = FlowableUtil.getNodeInfo(null, deploymentId, "3");
        if (StringUtils.isNotBlank(startNodeInfo)) {
            JSONArray startNodeInfoAry = (JSONArray) JSON.parse(startNodeInfo);
            JSONArray businessKeyAry = (JSONArray) JSON.parse(businessKey);
            for (int i = 0; i < startNodeInfoAry.size(); i++) {
                for (int j = 0; j < businessKeyAry.size(); j++) {
                    JSONObject startNodeJSONObject = startNodeInfoAry.getJSONObject(i);
                    JSONObject jsonObject = businessKeyAry.getJSONObject(j);
                    String fFormId = jsonObject.getString("F_FormId");
                    if (StringUtil.equals(startNodeJSONObject.getString("F_Id"), fFormId)) {
                        JSONObject retObject = new JSONObject();
                        String fId = jsonObject.getString("F_Id");
                        retObject.put("F_Id", fFormId);
                        // 表单配置信息
                        XjrFormSchemeInfo formSchemeInfo = formSchemeInfoService.getById(fFormId);
                        if (formSchemeInfo != null) {
                            retObject.put("F_Name", formSchemeInfo.getName());
                            String schemeid = formSchemeInfo.getSchemeId();
                            XjrFormScheme formScheme = formSchemeService.getById(schemeid);
                            if (formScheme != null) {
                                String retContentStr = formScheme.getScheme();
                                JSONObject retContent = (JSONObject) JSON.parse(retContentStr);
                                retObject.put("F_Scheme", retContent);
                            }
                        }
                        Integer type = jsonObject.getInteger("F_Type");
                        Map<String, Object> customFormData = null;
                        if (CollectionUtil.isNotEmpty(formInfoArray)) {
                            for (Object o : formInfoArray) {
                                JSONObject formInfoObj = (JSONObject) o;
                                if (StringUtil.equals(formInfoObj.getJSONObject("formInfo").getString("F_FormId"), fFormId)) {
                                    customFormData = formInfoObj.getJSONObject("formData");
                                }
                            }
                        }
                        if (customFormData == null) {
                            if (type != null && type == 2) {
                                //系统表单
                                String urlAddress = jsonObject.getString("F_UrlAddress");
                                customFormData = getSystemFormData(fId, urlAddress);
                            } else {
                                customFormData = formSchemeInfoService.getCustomFormData(fFormId, fId);
                            }
                        }
                        retObject.put("primaryKey", fId);
                        retObject.put("F_Data", customFormData);
                        retAry.add(retObject);
                        break;
                    }
                }
            }
            retObj.put("formInfo", retAry);
            retObj.put("nwfSchemeInfoId", nwfSchemeInfoId);
            // 流程模板名称
            XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(nwfSchemeInfoId);
            if (xjrNwfSchemeinfo != null) {
                retObj.put("nwfSchemeInfoName", xjrNwfSchemeinfo.getName());
                retObj.put("nwfSchemeInfoCode", xjrNwfSchemeinfo.getCode());
                retObj.put("modelId", xjrNwfSchemeinfo.getModelId());
            } else {
                retObj.put("nwfSchemeInfoName", "");
                retObj.put("nwfSchemeInfoCode", "");
                retObj.put("modelId", "");
            }
        }
        return retObj;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/10
     * @Param:[startNumber, pageSize]
     * @return:java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
     * @Description:查询所有的流程实例
     */
    public static List<Map<String, Object>> listAllProcess(GetPageListDto dto) {
        //获取用户缓存
        List<XjrBaseUser> xjrBaseUserlist = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.USER_LIST_CACHE_KEY);
        log.info("【查询所有的流程实例】");
        List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().orderByProcessInstanceStartTime().desc().listPage(dto.getLimit(), dto.getSize());
        long count = historyService.createHistoricProcessInstanceQuery().orderByProcessInstanceStartTime().desc().count();
        List<Map<String, Object>> retList = new ArrayList<>();
        for (HistoricProcessInstance his : list) {
            // 部署ID
            String deploymentId = his.getDeploymentId();
            // 获取流程实例
            String processInstanceId = his.getId();
            Map<String, Object> map = new HashMap<>(16);
            map.put("count", count);
            // 任务名称
            List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
            if (!Collections.isEmpty(taskList)) {
                // 正在执行的任务
                Task task = taskList.get(0);
                String taskId = task.getId();
                ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
                // 判断是否有设置任务命名规则
//                String taskName = taskNameRule(processInstance.getDeploymentId(), processInstanceId);
                map.put("taskName", task.getName());
                // 等级
                map.put("priority", task.getPriority());
                // 任务id
                map.put("taskId", taskId);
            } else {
                // 历史任务的查询
                List<HistoricActivityInstance> hisProcessInstanceList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
                HistoricActivityInstance hisProcessInstance = hisProcessInstanceList.get(hisProcessInstanceList.size() - 1);
                List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).list();
                HistoricTaskInstance historicTaskInstance = historicTaskInstanceList.get(historicTaskInstanceList.size() - 1);
                String hisTaskId = historicTaskInstance.getId();
                // 判断是否有设置任务命名规则
//                String taskName = taskNameRule(deploymentId, processInstanceId);
                // 任务
                map.put("taskName", StringUtils.isBlank(hisProcessInstance.getActivityName()));
                // 等级
                map.put("priority", historicTaskInstance.getPriority());
                // 任务id
                map.put("taskId", hisTaskId);
            }
            // 流水号
            XjrBaseTempfield xjrTempKeyvalue = xjrBaseTempfieldService.getByIdAndType(processInstanceId, "19");
            map.put("serialNumber", xjrTempKeyvalue != null ? xjrTempKeyvalue.getFvalue() : "");
            // 标题 根据实例Id查询流程模板名称
            String processDefinitionId = his.getProcessDefinitionId();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
            if (processDefinition != null) {
                String nwfSchemeInfoId = processDefinition.getDescription();
                XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(nwfSchemeInfoId);
                if (xjrNwfSchemeinfo != null) {
                    // 流程模板名称
                    map.put("schemeName", xjrNwfSchemeinfo.getName());
                } else {
                    map.put("schemeName", "");
                }
            }
            // 任务发起人
            String startUserId = his.getStartUserId();
            Optional<XjrBaseUser> xjrBaseUserOptional = xjrBaseUserlist.stream().filter(x -> x.getUserId().equals(startUserId)).findFirst();
            if (xjrBaseUserOptional.isPresent()) {
                String fRealname = xjrBaseUserOptional.get().getRealName();
                // 任务发起人
                map.put("startUser", fRealname);
            }
            // 开始时间
            map.put("startTime", his.getStartTime());
            // 流程实例ID
            map.put("processInstanceId", processInstanceId);
            retList.add(map);
        }
        return retList;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/10
     * @Param:[processInstanceId, deploymentId]
     * @return:java.lang.StringBuilder
     * @Description:测试修改流程版本
     */
    public static StringBuilder testChangeProcessVer(String processInstanceId, String deploymentId) throws
            Exception {
        StringBuilder stringBuilder = new StringBuilder("控制台：开始进行变更流程测试");
        // 根据deploymentId获取nwfschemeinfoId
        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
        String nwfSchemeInfoId = definition.getDescription();
        // 1.获取当前版本json和要替换版本的json
        // 替换后的json
        JSONArray changedChildShapes = null;
        XjrBaseTempfield tempKeyValue = xjrBaseTempfieldService.getByIdAndType(nwfSchemeInfoId + "_" + deploymentId, "3");
        if (tempKeyValue != null) {
            String changedJson = tempKeyValue.getFvalue();
            JSONObject changedJsonObj = (JSONObject) JSON.parse(changedJson);
            changedChildShapes = (JSONArray) changedJsonObj.get("childShapes");
        }
        // 当前的json
        JSONArray currentChildShapes = null;
        XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(nwfSchemeInfoId);
        if (xjrNwfSchemeinfo != null) {
            String currentDeploymentId = xjrNwfSchemeinfo.getDeploymentId();
            XjrBaseTempfield currentTempKeyValue = xjrBaseTempfieldService.getByIdAndType(nwfSchemeInfoId + "_" + currentDeploymentId, "3");
            if (currentTempKeyValue != null) {
                String currentJson = currentTempKeyValue.getFvalue();
                JSONObject currentJsonobj = (JSONObject) JSON.parse(currentJson);
                currentChildShapes = (JSONArray) currentJsonobj.get("childShapes");
            }
        }
        // 2.取当前任务之前的任务集合
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).list();
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        // 流程发起人
        // 3.发起新的流程
        // 验证开始节点的表单是否一致
        JSONObject changedStartNodeObj = (JSONObject) changedChildShapes.get(0);
        String resourceId = changedStartNodeObj.getString("resourceId");
        boolean canStartProcess = JsonUtil.comparisonJson(currentChildShapes, changedChildShapes, resourceId);
        stringBuilder.append("控制台：开始进行“开始”节点对比");
        stringBuilder.append("\r\n");
        if (canStartProcess) {
            stringBuilder.append("控制台：“开始”节点对比成功，进入下一节点对比");
            stringBuilder.append("\r\n");
        } else {
            stringBuilder.append("控制台：“开始”节点对比失败");
            stringBuilder.append("\r\n");
        }
        // 4.完结任务
        String lastTaskName = "";
        for (int i = 0; i < list.size(); i++) {
            HistoricTaskInstance historicTaskInstance = list.get(i);
            // 任务名
            String taskName = historicTaskInstance.getName();
            // 任务处理人
            String assignee = historicTaskInstance.getAssignee();
            // 任务的definitionKey
            String currentActId = historicTaskInstance.getTaskDefinitionKey();
            if (StringUtils.isBlank(assignee)) {
                break;
            }
            // 对比版本改变前后的json，如果返回为true则完结任务
            stringBuilder.append("控制台：开始进行" + taskName + "节点对比");
            stringBuilder.append("\r\n");
            boolean canComplete = JsonUtil.comparisonJson(currentChildShapes, changedChildShapes, currentActId);
            if (canComplete) {
                lastTaskName = taskName;
                stringBuilder.append("控制台：" + taskName + "节点对比成功，进入下一节点对比");
                stringBuilder.append("\r\n");
            } else {
                lastTaskName = taskName;
                stringBuilder.append("控制台：" + taskName + "节点对比失败");
                stringBuilder.append("\r\n");
                break;
            }
        }
        stringBuilder.append("---------------------------");
        stringBuilder.append("\r\n");
        stringBuilder.append("控制台：变更流程测试结束");
        stringBuilder.append("\r\n");
        stringBuilder.append("控制台：结果：预计流程可扭转至" + lastTaskName + "节点");
        return stringBuilder;
    }

    //对比流程属性
    public static JSONObject compareProperties(JSONObject currentProperties, JSONObject
            changedProperties, String startUserId) {
        //先判断之前的发起人有无发起流程权限
        JSONArray schemeAuthList = changedProperties.getJSONArray("schemeAuthList");
        boolean flag = false;
        if (CollectionUtil.isNotEmpty(schemeAuthList)) {
            for (int i = 0; i < schemeAuthList.size(); i++) {
                JSONObject authListJSONObject = schemeAuthList.getJSONObject(i);
                Integer objType = authListJSONObject.getInteger("F_ObjType");
                String objId = authListJSONObject.getString("F_ObjId");
                if (objType == 1) {
                    List<XjrBaseUser> xjrBaseUsers = userRelationService.getUsersOfObject(objId, 2);
                    Map<String, XjrBaseUser> xjrBaseUserMap = xjrBaseUsers.stream().collect(Collectors.toMap(s -> s.getUserId(), s -> s));
                    if (xjrBaseUserMap.get(startUserId) != null) {
                        flag = true;
                    }
                }
                //角色
                if (objType == 2) {
                    List<XjrBaseUser> xjrBaseUsers = userRelationService.getUsersOfObject(objId, 1);
                    Map<String, XjrBaseUser> xjrBaseUserMap = xjrBaseUsers.stream().collect(Collectors.toMap(s -> s.getUserId(), s -> s));
                    if (xjrBaseUserMap.get(startUserId) != null) {
                        flag = true;
                    }
                }
                //用户
                if (objType == 3) {
                    String userId = objId;
                    if (userId.equals(startUserId)) {
                        flag = true;
                    }
                }
                //所有
                if (objType == 4) {
                    flag = true;
                }
            }
        }
        //判断是否为管理员
        List<XjrBaseRole> roles = roleService.getRolesByUserId(startUserId);
        for (XjrBaseRole role : roles) {
            boolean adminRole = roleService.isAdminRole(role.getRoleId());
            if (adminRole) {
                flag = true;
            }
        }
        //如果为管理员或者有权限发起则比较下面的属性
        JSONObject result = new JSONObject();
        if (flag) {
            boolean ruleName = com.xjrsoft.core.tool.jackson.JsonUtil.compareJSONArray(currentProperties.getJSONArray("ruleName"), changedProperties.getJSONArray("ruleName"));
            if (!ruleName) {
                result.put("isSame", false);
                result.put("information", "流程命名规则不一样,流程结束");
                return result;
            }
            if (currentProperties.getInteger("F_Agree") != changedProperties.getInteger("F_Agree")) {
                result.put("isSame", false);
                result.put("information", "流程自动同意规则不一样,流程结束");
                return result;
            }
            if (currentProperties.getBoolean("F_Assign") != changedProperties.getBoolean("F_Assign")) {
                result.put("isSame", false);
                result.put("information", "由上一用户节点审批人指定下一用户节点审批人规则不一样,流程结束");
                return result;
            }
            if (currentProperties.getInteger("F_Handle") != changedProperties.getInteger("F_Handle")) {
                result.put("isSame", false);
                result.put("information", "无对应处理人规则不一样,流程结束");
                return result;
            }
            if (currentProperties.getBoolean("isInheritStartNode") != changedProperties.getBoolean("isInheritStartNode")) {
                result.put("isSame", false);
                result.put("information", "用户任务是否继承开始节点表单规则不一样,流程结束");
                return result;
            }
            Boolean relevanceTask = com.xjrsoft.core.tool.jackson.JsonUtil.compareJsonObject(currentProperties.getJSONObject("relevanceTask"), changedProperties.getJSONObject("relevanceTask"));
            if (!relevanceTask) {
                result.put("isSame", false);
                result.put("information", "关联任务不一样,流程结束");
                return result;
            }
            boolean parameters = com.xjrsoft.core.tool.jackson.JsonUtil.compareJSONArray(currentProperties.getJSONArray("parameters"), changedProperties.getJSONArray("parameters"));
            if (!parameters) {
                result.put("isSame", false);
                result.put("information", "流程参数不一样,流程结束");
                return result;
            }
            result.put("isSame", true);
            result.put("information", "");
        } else {
            result.put("isSame", false);
            result.put("information", "流程发起人没有新流程发起权限,流程结束");
        }
        return result;
    }

    //比较当前节点配置是否相等
    public static List<String> compareNode(JSONArray currentChildShapes, JSONArray changedChildShapes, String
            resourceId, List<String> resourceIds, Set<String> activityIds) {
        List<String> result = new ArrayList<>();
        if (resourceIds.contains(resourceId)) {
            //已经比较过了
            return result;
        } else {
            resourceIds.add(resourceId);
        }
        for (int i = 0; i < changedChildShapes.size(); i++) {

            JSONObject changedChildShapeJsonObject = changedChildShapes.getJSONObject(i);
            String changedResourceId = changedChildShapeJsonObject.getString("resourceId");
            if (StringUtil.equals(changedResourceId, resourceId)) {
                for (int j = 0; j < currentChildShapes.size(); j++) {
                    JSONObject currentChildShapesJSONObject = currentChildShapes.getJSONObject(j);
                    String currentResourceId = currentChildShapesJSONObject.getString("resourceId");
                    if (activityIds.contains(currentResourceId)) {
                        if (StringUtil.equals(resourceId, currentResourceId)) {
                            //比较节点的配置
                            Boolean aBoolean = com.xjrsoft.core.tool.jackson.JsonUtil.compareJsonObject(currentChildShapesJSONObject, changedChildShapeJsonObject);
                            result.add(resourceId);
                            if (aBoolean) {
                                //如果相等则对比下一个节点
                                result.add(resourceId);
                                String changedType = changedChildShapeJsonObject.getJSONObject("properties").getString("type");
                                if (StringUtil.equals(changedType, "bpmn:SequenceFlow")) {
                                    JSONObject target = changedChildShapeJsonObject.getJSONObject("target");
                                    if (target != null) {
                                        String outResourceId = target.getString("resourceId");
                                        result.addAll(compareNode(currentChildShapes, changedChildShapes, outResourceId, resourceIds, activityIds));
                                    }
                                } else {
                                    JSONArray outgoings = changedChildShapeJsonObject.getJSONArray("outgoing");
                                    if (CollectionUtil.isNotEmpty(outgoings)) {
                                        for (Object outgoing : outgoings) {
                                            JSONObject outgoingObj = (JSONObject) outgoing;
                                            String outResourceId = outgoingObj.getString("resourceId");
                                            result.addAll(compareNode(currentChildShapes, changedChildShapes, outResourceId, resourceIds, activityIds));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return result;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/10
     * @Param:[processInstanceId]
     * @return:com.alibaba.fastjson.JSONArray
     * @Description:
     */
//    public static JSONArray getRelationTaskList(String processInstanceId) throws Exception {
//        String nwfSchemeInfoId = "";
//        String processDefinitionId = "";
//        JSONArray retAry = new JSONArray();
//        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//        if (processInstance != null) {
//            processDefinitionId = processInstance.getProcessDefinitionId();
//        } else {
//            HistoricProcessInstance hisProcess = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//            processDefinitionId = hisProcess.getProcessDefinitionKey();
//
//        }
//        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
//        nwfSchemeInfoId = processDefinition.getDescription();
//        String fkey = nwfSchemeInfoId + "_" + processInstanceId;
//        XjrBaseTempfield xjrTempKeyvalue = xjrBaseTempfieldService.getByIdAndType(fkey, "22");
//        if (xjrTempKeyvalue != null) {
//            // 关联任务的信息
//            String colValue = xjrTempKeyvalue.getValue_();
//            JSONArray relationTaskList = JSONArray.parseArray(colValue);
//            for (int i = 0; i < relationTaskList.size(); i++) {
//                JSONObject relationTask = relationTaskList.getJSONObject(i);
//                String title = relationTask.getString("title");
//                String relationTaskProInsId = relationTask.getString("processInstanceId");
//                JSONObject relationTaskInfo = getRelationTaskInfo(relationTaskProInsId);
//                relationTaskInfo.put("title", title);
//                relationTaskInfo.put("processInstanceId", relationTaskProInsId);
//                retAry.add(relationTaskInfo);
//            }
//        }
//        return retAry;
//    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/10
     * @Param:[relevanceTask, currentUserId, pnum, psize]
     * @return:com.baomidou.mybatisplus.extension.plugins.pagination.Page<Record>
     * @Description: 获取关联任务列表
     */
//    public static Page<Record> getRelationTask(JSONObject relevanceTask, String currentUserId, Integer pnum, Integer psize) {
//        String sql = "SELECT DISTINCT RES.*, DEF.KEY_ AS PROC_DEF_KEY_, DEF.NAME_ AS PROC_DEF_NAME_, DEF.VERSION_ AS PROC_DEF_VERSION_,"
//                + "	DEF.DEPLOYMENT_ID_ AS DEPLOYMENT_ID_ FROM ACT_HI_PROCINST RES LEFT JOIN  xjr_temp_keyvalue XTK ON RES.PROC_INST_ID_ = XTK. col_key"
//                + " LEFT OUTER JOIN ACT_RE_PROCDEF DEF ON RES.PROC_DEF_ID_ = DEF.ID_ WHERE 1 = 1  AND RES.PROC_DEF_ID_ LIKE ?";
//        // 流程模板信息ID
//        String nwfSchemeInfoId = relevanceTask.getString("F_ObjId");
//        // 获取definitionId
//        XjrNwfSchemeinfo xjrNwfSchemeinfo = staXjrNwfSchemeInfoService.getById(nwfSchemeInfoId);
//        String schemeName = "";
//        if (xjrNwfSchemeinfo != null) {
//            schemeName = xjrNwfSchemeinfo.getFName();
//            String fDeploymentId = xjrNwfSchemeinfo.getFDeploymentid();
//            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(fDeploymentId).singleResult();
//            fkey = processDefinition.getFkey();
//        }
//        sqlPara.addPara(fkey + "%");
//        // 流程状态:流程未结束，流程结束
//        String taskStatu = relevanceTask.getString("tStatu");
//        boolean isFinnshed = StringUtils.equalsIgnoreCase(taskStatu, "approveAdopt");
//        // 权限:发起人发起，所有
//        String authority = relevanceTask.getString("tAuthority");
//        // 限制发起人发起
//        if (StringUtils.equalsIgnoreCase(authority, "createUser")) {
//            sql += " AND RES.START_USER_ID_ = ?";
//            sqlPara.addPara(currentUserId);
//        }
//        // 流程状态
//        if (isFinnshed) {
//            // 已经结束
//            sql += " AND RES.END_TIME_ IS NOT NULL";
//        } else {
//            // 还在运行中
//            sql += " AND RES.END_TIME_ IS NULL";
//        }
//        sql += " AND RES.DELETE_REASON_ IS NULL AND XTK." + My_symbol.DB_QUOTES + "col_key" + My_symbol.DB_QUOTES
//                + " IS NULL ORDER BY RES.START_TIME_ DESC";
//        sqlPara.setSql(sql);
//        List<Record> processAry = new ArrayList<>();
////				List<Record> list = Db.find(sqlPara);
//        Page<Record> page = Db.paginate(pnum, psize, sqlPara);
//        List<Record> list = page.getList();
//        for (Record record : list) {
////			JSONObject processObj = new JSONObject();
//            Record retRecord = new Record();
//            String taskId = "";
//            String taskName = "";
//            String startUser = "";
//            Integer priority = 0;
//            String createTime = "";
//            String processInstanceId = record.getStr("PROC_INST_ID_");
//            if (isFinnshed) {
//                // 流程结束
//                // 获取流程实例
//                HistoricProcessInstance hisProcess = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//                HistoricTaskInstance hisTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).singleResult();
//                // 获取节点的名称
//                String activitiId = hisTaskInstance.getTaskDefinitionKey();
//                HistoricActivityInstance historicActivityInstance = historyService.createHistoricActivityInstanceQuery().activityId(activitiId).list().get(0);
//                retRecord.set("btnName", historicActivityInstance.getActivityName());
//                priority = hisTaskInstance.getPriority();
//                taskId = hisTaskInstance.getId();
//                taskName = hisTaskInstance.getName();
//                Date startTime = hisProcess.getStartTime();
//                createTime = DateUtil.format(startTime, "yyyy-MM-dd HH:mm:ss");
//                startUser = hisProcess.getStartUserId();
//            } else {
//                // 流程未结束
//                // 获取流程实例
//                ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//                Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
//                // 获取节点的名称
//                String activitiId = task.getTaskDefinitionKey();
//                HistoricActivityInstance historicActivityInstance = historyService.createHistoricActivityInstanceQuery().activityId(activitiId).list().get(0);
//                retRecord.set("btnName", historicActivityInstance.getActivityName());
//                priority = task.getPriority();
//                taskId = task.getId();
//                taskName = task.getName();
//                Date startTime = processInstance.getStartTime();
//                createTime = DateUtil.format(startTime, "");
//                startUser = processInstance.getStartUserId();
//            }
//            retRecord.set("createTime", createTime);
//            retRecord.set("priority", priority);
//            retRecord.set("processInstanceId", processInstanceId);
//            retRecord.set("schemeName", schemeName);
//            // 流水号
//            XjrBaseTempfield xjrTempKeyvalue = staXjrBaseTempfieldService.getByIdAndType(taskId, "19");
//            if (xjrTempKeyvalue != null) {
//                String colValue = xjrTempKeyvalue.getFValue();
//                retRecord.set("serialNumber", colValue);
//            } else {
//                retRecord.set("serialNumber", "");
//            }
//            retRecord.set("startUser", startUser);
//            retRecord.set("taskId", taskId);
//            retRecord.set("taskName", taskName);
//            retRecord.set("nwfSchemeInfoId", nwfSchemeInfoId);
//            processAry.add(retRecord);
//        }
//        page.setList(processAry);
//        return page;
//    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/12/28
     * @Param:[processInstanceId]
     * @return:
     * @Description:根据流程实例id获取 流程设计信息ID
     */
    public static String getNwfSchemInfoIdByInsId(String processInstanceId) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (processInstance != null) {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(processInstance.getDeploymentId()).singleResult();
            if (processDefinition != null) {
                return processDefinition.getDescription();
            }
        }
        return null;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2021/1/26
     * @Param:[taskId]
     * @return:java.lang.String
     * @Description:获取任务候选人/审批人
     */
    public static JSONObject getTaskCandidateUser(String processInstanceId) {
        List<XjrBaseUser> xjrBaseUserlist = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.USER_LIST_CACHE_KEY);
        JSONObject retObject = new JSONObject();
        JSONArray candidateUserArray = new JSONArray();
        JSONArray assigneeArray = new JSONArray();
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        for (Task task : taskList) {
            List<HistoricIdentityLink> list = historyService.getHistoricIdentityLinksForTask(task.getId());
            for (HistoricIdentityLink historicIdentityLink : list) {
                String type = historicIdentityLink.getType();
                String userId = historicIdentityLink.getUserId();
                Optional<XjrBaseUser> xjrBaseUserOptional = xjrBaseUserlist.stream().filter(x -> x.getUserId().equals(userId)).findFirst();
                if (xjrBaseUserOptional.isPresent()) {
                    if (StringUtils.equalsIgnoreCase(type, "candidate")) {
                        candidateUserArray.add(xjrBaseUserOptional.get());
                    } else {
                        assigneeArray.add(xjrBaseUserOptional.get());
                    }
                }
            }
        }
        retObject.put("assignee", assigneeArray);
        retObject.put("candidateUsers", candidateUserArray);
        return retObject;
    }


    public static JSONArray getMultiInstanceTaskCandidateUser(String processInstanceId) {
        List<XjrBaseUser> xjrBaseUserlist = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.USER_LIST_CACHE_KEY);
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        JSONArray candidateUserArray = new JSONArray();
        for (Task task : taskList) {
            Object variable = taskService.getVariable(task.getId(), task.getTaskDefinitionKey() + StringPool.UNDERSCORE + "usernamelist");
            JSONArray jsonArray = JSONArray.parseArray(JSONObject.toJSONString(variable));
            if (CollectionUtil.isNotEmpty(jsonArray)) {
                for (int i = 0; i < jsonArray.size(); i++) {
                    String userId = jsonArray.getString(i);
                    Optional<XjrBaseUser> xjrBaseUserOptional = xjrBaseUserlist.stream().filter(x -> x.getUserId().equals(userId)).findFirst();
                    if (xjrBaseUserOptional.isPresent()) {
                        XjrBaseUser user = xjrBaseUserOptional.get();
                        if (!candidateUserArray.contains(user)) {
                            candidateUserArray.add(user);
                        }
                    }
                }
            }
        }
        return candidateUserArray;
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2021/1/26
     * @Param:[taskId, userId]
     * @return:java.lang.Object
     * @Description:任务指派审批人
     */
    public static void assign(String taskId, String userId) {
        taskService.addCandidateUser(taskId, userId);
    }


    //获取消息策略
    public static List<Integer> getMessageTypes(String resourceId, String fjson) {
        ArrayList<Integer> messageTypes = new ArrayList<>();
        if (StringUtils.isNotEmpty(fjson)) {
            JSONObject jsonObject = JSONObject.parseObject(fjson);
            JSONArray childShapes = jsonObject.getJSONArray("childShapes");
            for (int i = 0; i < childShapes.size(); i++) {
                String resourceId1 = childShapes.getJSONObject(i).getString("resourceId");
                if (StringUtils.isNotEmpty(resourceId1) && resourceId1.equals(resourceId)) {
                    JSONArray messageType = childShapes.getJSONObject(i).getJSONObject("properties").getJSONArray("messageTypes");
                    if (messageType != null) {
                        for (Object message : messageType) {
                            messageTypes.add(Integer.valueOf(message.toString()));
                        }
                        break;
                    }
                }
            }
        }
        return messageTypes;
    }

//    public static ProcessEngine getProcessEngine() {
//        if (engine == null) {
//            // 使用默认的配置文件名称（activiti.cfg.xml）创建引擎对象
//            engine = ProcessEngines.getDefaultProcessEngine();
//        }
//        return engine;
//    }

    //给系统表单数据添加流程信息
    public static <T> List<T> systemFormList(List<T> records, String moudleId) {
        XjrFormSchemeInfo xjrFormSchemeInfo = formSchemeInfoService.getOne(Wrappers.<XjrFormSchemeInfo>query().lambda().eq(XjrFormSchemeInfo::getSchemeId, moudleId).eq(XjrFormSchemeInfo::getDeleteMark, DeleteMarkEnum.NODELETE.getCode()).eq(XjrFormSchemeInfo::getEnabledMark, EnabledMarkEnum.ENABLED.getCode()));
        XjrFormScheme xjrFormScheme = formSchemeService.getById(moudleId);
        if (xjrFormScheme != null) {
            JSONObject schemeJson = JSONObject.parseObject(xjrFormScheme.getScheme());
            String mainPk = StringPool.EMPTY;
            if (schemeJson != null) {
                JSONArray dbTables = schemeJson.getJSONArray(FormConstants.DB_TABLE);
                if (CollectionUtil.isNotEmpty(dbTables)) {
                    for (Object dbTableObj : dbTables) {
                        JSONObject dbTable = (JSONObject) dbTableObj;
                        if (StringUtil.isBlank(dbTable.getString(FormConstants.DB_TABLE_RELATION_NAME))) {
                            mainPk = dbTable.getString(FormConstants.DB_TABLE_PK);
                            break;
                        }
                    }
                    //获取主键名字
                    String name = "";
                    if (CollectionUtil.isNotEmpty(records)) {
                        Field[] fields = records.get(0).getClass().getDeclaredFields();
                        for (int i = 0; i < fields.length; i++) {
                            JsonProperty annotation = fields[i].getAnnotation(JsonProperty.class);
                            if (null != annotation) {
                                String value = annotation.value();
                                if (StringUtil.equalsIgnoreCase(value, mainPk)) {
                                    name = fields[i].getName();
                                    break;
                                }
                            }
                        }
                    }
                    String deploymentId = "";
                    String nwfSchemeinfoId = "";
                    String formId = "";
                    if (xjrFormSchemeInfo != null) {
                        formId = xjrFormSchemeInfo.getId();
                        nwfSchemeinfoId = xjrFormSchemeInfo.getNwfSchemeinfoId();
                        XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(nwfSchemeinfoId);
                        if (xjrNwfSchemeinfo != null) {
                            deploymentId = xjrNwfSchemeinfo.getDeploymentId();
                        }
                    }
                    for (T record : records) {
                        Integer flowStatus = null;
                        //获取流程id
                        String id = BeanUtil.getProperty(record, name).toString();
//                String id = BeanUtil.getProperty(record, "fId").toString();
                        HistoricProcessInstance historicProcessInstance = null;
                        List<HistoricProcessInstance> historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery().variableValueEquals(formId + StringPool.UNDERSCORE + id).notDeleted().list();
                        for (HistoricProcessInstance processInstance : historicProcessInstanceList) {
                            XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(processInstance.getId(), "18");
                            if (xjrBaseTempfield == null) {
                                historicProcessInstance = processInstance;
                                break;
                            }
                        }
                        if (historicProcessInstance == null) {
                            //未发起流程或未完成加入到回收站中可重新发起
                            if (StringUtil.isBlank(nwfSchemeinfoId)) {
                                //未绑定表单
                                flowStatus = 0;
                            } else {
                                flowStatus = 1;
                            }
                        } else {
                            //查看流程是否被结束
                            QueryWrapper<XjrBaseTempfield> queryWrapper = new QueryWrapper<>();
                            queryWrapper.lambda().eq(StringUtil.isNotBlank(historicProcessInstance.getId()), XjrBaseTempfield::getFkey, historicProcessInstance.getId()).eq(XjrBaseTempfield::getType, "33").like(XjrBaseTempfield::getFvalue, "流程被结束");
                            XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getOne(queryWrapper);
                            if (historicProcessInstance.getEndTime() != null || xjrBaseTempfield != null) {
                                //已完成
                                flowStatus = 3;
                            } else {
                                //审批中
                                flowStatus = 2;
                            }
                        }
                        if (BeanUtil.checkFields(record, "formId"))
                            BeanUtil.setProperty(record, "formId", formId);
                        if (BeanUtil.checkFields(record, "flowStatus"))
                            BeanUtil.setProperty(record, "flowStatus", flowStatus.toString());
                        if (BeanUtil.checkFields(record, "nwfSchemeinfoId"))
                            BeanUtil.setProperty(record, "nwfSchemeinfoId", nwfSchemeinfoId);
                        if (BeanUtil.checkFields(record, "deploymentId"))
                            BeanUtil.setProperty(record, "deploymentId", deploymentId);
                    }
                }
            }
        }
        return records;
    }

    //获取当前传阅人
    public static List<String> getManualUser(String processInstanceId, String actId) throws Exception {
        //添加当前节点的传阅人
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        List<HistoricActivityInstance> histList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
        String deployId = historicProcessInstance.getDeploymentId();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
        String nwfSchemeInfoId = processDefinition.getDescription();
        String version = String.valueOf(processDefinition.getVersion());
        String key = nwfSchemeInfoId + StringPool.UNDERSCORE + actId + StringPool.UNDERSCORE + version;
        ArrayList<XjrBaseTempfield> xjrBaseTempfields = new ArrayList<>();
        xjrBaseTempfields.add(xjrBaseTempfieldService.getByIdAndType(key, "7"));
        xjrBaseTempfields.add(xjrBaseTempfieldService.getByIdAndType(processInstanceId + "_" + actId, "7"));
        ArrayList<String> results = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(xjrBaseTempfields)) {
            // 更新temp表的数据
            // 更新xjr_temp表数据
            for (XjrBaseTempfield xjrTempKeyvalue : xjrBaseTempfields) {
                if (xjrTempKeyvalue != null) {
                    String forwarderList = xjrTempKeyvalue.getFvalue();
                    xjrBaseTempfieldService.updateById(xjrTempKeyvalue);
                    if (StrUtil.isNotBlank(forwarderList)) {
                        Set<String> userIds = FlowableUtil.checkUsers(processInstanceId, histList, JSONArray.parseArray(forwarderList));
                        if (CollectionUtil.isNotEmpty(userIds)) {
                            results.addAll(userIds);
                        }
                    }
                }
            }
        }
        return results;
    }

    //获取隐藏组件的值
    public static String gethideComponentsValue(JSONObject formObj) throws Exception {
        String value = "";
        String type = formObj.getString("hideComponentsType");
        if (StringUtil.equals(type, "value")) {
            value = formObj.getString("hideComponentsvalue");
        } else if (StringUtil.equals(type, "sql")) {
            JSONObject sqlConfig = formObj.getJSONObject("sqlConfig");
            String database = sqlConfig.getString("database");
            String field = sqlConfig.getString("field");
            String sql = sqlConfig.getString("sql");
            List<Map<String, Object>> dataByColumns = databaselinkService.getDataByColumns(database, field, sql);
            if (CollectionUtil.isNotEmpty(dataByColumns)) {
                Map<String, Object> map = dataByColumns.get(0);
                Object o = map.get(field);
                value = String.valueOf(o);
            }
        } else if (StringUtil.equals(type, "api")) {
            JSONObject apiConfig = formObj.getJSONObject("apiConfig");
            String interfaceId = apiConfig.getString("id");
            String field = apiConfig.getString("field");
            JSONArray apiInputParams = apiConfig.getJSONArray("apiInputParams");
            Map<String, String> paramMap = new HashMap<>();
            HttpServletRequest request = WebUtil.getRequest();
            if (CollectionUtil.isNotEmpty(apiInputParams)) {
                for (int i = 0; i < apiInputParams.size(); i++) {
                    JSONObject jsonObject = apiInputParams.getJSONObject(i);
                    paramMap.put(jsonObject.getString("F_ParamKey"), jsonObject.getString("F_ParamValue"));
                }
            }
            MediaType JSONType = MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE);
            okhttp3.RequestBody body = okhttp3.RequestBody.create(JSONType, JSON.toJSONString(paramMap));
            String host = serverConfig.getLocalUrl();
            String address = host + StringPool.SLASH + "xjr-interface-info" + StringPool.SLASH + "execute" + StringPool.SLASH + interfaceId;
            OkHttpClient client = new OkHttpClient();
            HttpUrl parse = HttpUrl.parse(address);
            HttpUrl.Builder builder = Objects.requireNonNull(parse).newBuilder();
            Request.Builder url = new Request.Builder().url(builder.build());
            url.addHeader("isWorkFlow", "true");
            url.addHeader("Authorization", request.getHeader("Authorization"));
            Request req = url.post(body).build();
            okhttp3.Response response = client.newCall(req).execute();
            if (response.isSuccessful()) {
                String responseBody = Objects.requireNonNull(response.body()).string();
                JSONObject responseBodyObj = JSONObject.parseObject(responseBody);
                if (responseBodyObj.getBoolean("success")) {
                    JSONObject data = responseBodyObj.getJSONObject("data");
                    if (CollectionUtil.isNotEmpty(data)) {
                        Object o = data.get(field);
                        if (o != null) {
                            value = String.valueOf(o);
                        }
                    }
                }
            }
        }
        return value;
    }
}
